diff --git a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/bean/BusWriteOffPassengersQueryRequest.java b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/bean/BusWriteOffPassengersQueryRequest.java index 6f07456c78..708819e436 100644 --- a/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/bean/BusWriteOffPassengersQueryRequest.java +++ b/OCH/mogo-och-bus/src/main/java/com/mogo/och/bus/bean/BusWriteOffPassengersQueryRequest.java @@ -1,6 +1,9 @@ package com.mogo.och.bus.bean; import com.mogo.cloud.passport.MoGoAiCloudClientConfig; +import com.mogo.eagle.core.data.BaseData; + +import java.util.List; /** * 查询核销乘客 @@ -21,4 +24,150 @@ public class BusWriteOffPassengersQueryRequest { public String getSn() { return sn; } + + /** + * @author: wangmingjun + * @date: 2021/10/19 + */ + public static class BusOrdersResponse extends BaseData { + public com.mogo.och.bus.bean.BusOrdersResponse.Result data; + public static class Result{ + public List orders; + } + + @Override + public String toString() { + return "BusOrdersResponse{" + + "data=" + data + + '}'; + } + } + + /** + * 网约车小巴路线接口请求响应结果 + * + * @author tongchenfei + */ + public static class BusRoutesResponse extends BaseData { + private BusRoutesResult data; + + public BusRoutesResult getResult() { + return data; + } + + public void setResult(BusRoutesResult data) { + this.data = data; + } + + @Override + public String toString() { + return "BusRoutesResponse{" + + "data=" + data + + '}'; + } + } + + /** + * 单个网约车小巴车站信息 + * + * @author tongchenfei + */ + public static class BusStationBean { + private int siteId; + private String name; + private int seq; + private double gcjLon; //高德 + private double gcjLat; //高德 + private double lon; //高精坐标 + private double lat; //高精坐标 + private int drivingStatus;//行驶信息,0初始值;1已经过;2当前站;3未到站 + private boolean leaving; + + public int getSiteId() { + return siteId; + } + + public String getName() { + return name; + } + + public int getSeq() { + return seq; + } + + public double getGcjLon() { + return gcjLon; + } + + public double getGcjLat() { + return gcjLat; + } + + public double getLon() { + return lon; + } + + public double getLat() { + return lat; + } + + public int getDrivingStatus() { + return drivingStatus; + } + + public boolean isLeaving() { + return leaving; + } + + public void setSiteId(int siteId) { + this.siteId = siteId; + } + + public void setName(String name) { + this.name = name; + } + + public void setSeq(int seq) { + this.seq = seq; + } + + public void setGcjLon(double gcjLon) { + this.gcjLon = gcjLon; + } + + public void setGcjLat(double gcjLat) { + this.gcjLat = gcjLat; + } + + public void setLon(double lon) { + this.lon = lon; + } + + public void setLat(double lat) { + this.lat = lat; + } + + public void setDrivingStatus(int drivingStatus) { + this.drivingStatus = drivingStatus; + } + + public void setLeaving(boolean leaving) { + this.leaving = leaving; + } + + @Override + public String toString() { + return "BusStationBean{" + + "siteId=" + siteId + + ", name='" + name + '\'' + + ", seq=" + seq + + ", gcjLon=" + gcjLon + + ", gcjLat=" + gcjLat + + ", lon=" + lon + + ", lat=" + lat + + ", drivingStatus=" + drivingStatus + + ", leaving=" + leaving + + '}'; + } + } } diff --git a/OCH/mogo-och-shuttle-passenger/.gitignore b/OCH/mogo-och-shuttle-passenger/.gitignore new file mode 100644 index 0000000000..42afabfd2a --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/README.md b/OCH/mogo-och-shuttle-passenger/README.md new file mode 100644 index 0000000000..6175119b78 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/README.md @@ -0,0 +1,15 @@ + + + + + +src + - androidTest Android 测试代码 + - basecommon 金旅开沃、接驳车 公用代码部分 + - jinlvvan 金旅开沃 独立代码部分 + - m1 金旅m1 独立代码部分 + - m2 金旅m2 独立代码部分 + - main 所有车型公用代码部分 + - shuttle 接驳车独立代码 因为接驳车和金旅开沃代码耦合厉害暂时放入到mogo-och-bus-passenger里面 + 后期会创建独立module和mogo-och-bus-passenger平级 + - test 普通代码测试 \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/build.gradle b/OCH/mogo-och-shuttle-passenger/build.gradle new file mode 100644 index 0000000000..0818ec952e --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/build.gradle @@ -0,0 +1,83 @@ +apply plugin: 'com.android.library' +apply plugin: 'com.alibaba.arouter' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-kapt' + +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" + + kapt { + useBuildCache = false + arguments { + arg("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' + } + } + + flavorDimensions "vehicle" + productFlavors { + // 车型:金旅星辰、开沃 小巴业务 + jinlvvan { + dimension "vehicle" + buildConfigField 'int', 'NEW_TEST', '0' + } + // 车型:金旅m1 小巴业务 + m1 { + dimension "vehicle" + buildConfigField 'int', 'NEW_TEST', '1' + } + + // 车型:金旅m1 小巴业务 + m2 { + dimension "vehicle" + buildConfigField 'int', 'NEW_TEST', '1' + } + } +} + +dependencies { + implementation fileTree(dir: "libs", include: ["*.jar"]) + implementation rootProject.ext.dependencies.kotlinstdlibjdk7 + implementation rootProject.ext.dependencies.androidxappcompat + implementation rootProject.ext.dependencies.arouter + implementation rootProject.ext.dependencies.androidxrecyclerview + implementation rootProject.ext.dependencies.material + kapt rootProject.ext.dependencies.aroutercompiler + implementation rootProject.ext.dependencies.rxandroid + implementation rootProject.ext.dependencies.androidxconstraintlayout + implementation rootProject.ext.dependencies.amapnavi3dmap + implementation project(":OCH:mogo-och-common-module") + compileOnly project(":libraries:mogo-map") + implementation project(':core:mogo-core-res') + testImplementation 'junit:junit:4.12' + +} + +apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString() \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/consumer-rules.pro b/OCH/mogo-och-shuttle-passenger/consumer-rules.pro new file mode 100644 index 0000000000..e69de29bb2 diff --git a/OCH/mogo-och-shuttle-passenger/gradle.properties b/OCH/mogo-och-shuttle-passenger/gradle.properties new file mode 100644 index 0000000000..2ed1ed2f42 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/gradle.properties @@ -0,0 +1,3 @@ +GROUP=com.mogo.och +POM_ARTIFACT_ID=och-bus-passenger +VERSION_CODE=1 diff --git a/OCH/mogo-och-shuttle-passenger/proguard-rules.pro b/OCH/mogo-och-shuttle-passenger/proguard-rules.pro new file mode 100644 index 0000000000..481bb43481 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/androidTest/java/com/mogo/och/bus/passenger/ExampleInstrumentedTest.java b/OCH/mogo-och-shuttle-passenger/src/androidTest/java/com/mogo/och/bus/passenger/ExampleInstrumentedTest.java new file mode 100644 index 0000000000..2685ade0a4 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/androidTest/java/com/mogo/och/bus/passenger/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.mogo.och.bus.passenger; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + assertEquals("com.mogo.och.bus.passenger.test", appContext.getPackageName()); + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/MogoOCHBusPassenger.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/MogoOCHBusPassenger.java new file mode 100644 index 0000000000..3bf45d5f18 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/MogoOCHBusPassenger.java @@ -0,0 +1,96 @@ +package com.mogo.och.bus.passenger; + +import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_TAXI_P; + +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.data.config.FunctionBuildConfig; +import com.mogo.eagle.core.function.call.setting.CallerMoGoUiSettingManager; +import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.eagle.core.utilcode.util.MultiDisplayUtils; +import com.mogo.och.bus.passenger.constant.BusPassengerConst; +import com.mogo.och.bus.passenger.ui.BusPassengerRouteFragment; +import com.mogo.och.common.module.wigets.video.VideoPlayerActivity; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * 网约车-Bus-乘客端 + * + * Created on 2022/3/29 + */ +@Route(path = BusPassengerConst.PATH) +public class MogoOCHBusPassenger implements IMogoOCH { + private static final String TAG = MogoOCHBusPassenger.class.getSimpleName(); + + private FragmentActivity mActivity; + private int mContainerId; + private BusPassengerRouteFragment mPassengerFragment; + + @Override + public void createCoverage(FragmentActivity activity, int containerId) { + + } + + @Nullable + @Override + public Fragment createCoverage(@Nullable FragmentActivity activity, @Nullable Integer containerId) { + this.mActivity = activity; + this.mContainerId = containerId; + showFragment(); + + if (AppIdentityModeUtils.isJL(FunctionBuildConfig.appIdentityMode)) { + MultiDisplayUtils.INSTANCE.startActWithSecond(activity, VideoPlayerActivity.class); + } + return null; + } + + @NotNull + @Override + public String getFunctionName() { + return null; + } + + @Override + public void onDestroy() { + // 若不调用finish, 设置中打开关闭UITouch,会造成och fragment 重叠 + if (mActivity == null) return; + mActivity.finish(); + } + + @Override + public void init(Context context) { + } + + /** + * 进入鹰眼模式,设置手势缩放地图失效 + */ + private void stepIntoVrMode() { + CallerLogger.INSTANCE.d( M_TAXI_P + TAG, "进入vr模式" ); + CallerMoGoUiSettingManager.INSTANCE.stepInDayMode();//白天模式 状态栏字体颜色变黑 + } + + private void showFragment() { + if (mPassengerFragment == null) { + CallerLogger.INSTANCE.d(M_TAXI_P + TAG, "准备add fragment======"); + mPassengerFragment = new BusPassengerRouteFragment(); + mActivity.getSupportFragmentManager().beginTransaction().add(mContainerId, mPassengerFragment).commitAllowingStateLoss(); + return; + } + CallerLogger.INSTANCE.d(M_TAXI_P + TAG, "准备show fragment"); + mActivity.getSupportFragmentManager().beginTransaction().show(mPassengerFragment).commitAllowingStateLoss(); + } + + private void hideFragment(){ + if (mPassengerFragment != null){ + mActivity.getSupportFragmentManager().beginTransaction().hide(mPassengerFragment).commitAllowingStateLoss(); + } + } + +} diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/adapter/BusPassengerLineStationsAdapter.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/adapter/BusPassengerLineStationsAdapter.java new file mode 100644 index 0000000000..565372b4a9 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/adapter/BusPassengerLineStationsAdapter.java @@ -0,0 +1,131 @@ +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; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.constraintlayout.widget.Group; +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; + +import static com.mogo.och.bus.passenger.constant.BusPassengerConst.STATION_STATUS_ARRIVING; +import static com.mogo.och.bus.passenger.constant.BusPassengerConst.STATION_STATUS_LEAVING; +import static com.mogo.och.bus.passenger.constant.BusPassengerConst.STATION_STATUS_STOPPED; + +/** + * @author: wangmingjun + * @date: 2022/4/6 + */ +public class BusPassengerLineStationsAdapter extends RecyclerView.Adapter { + + private Context mContext; + private List mStations; + + public BusPassengerLineStationsAdapter(Context context, List stations){ + this.mContext = context; + this.mStations = stations; + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from(mContext).inflate(R.layout.bus_p_stations_common_item,parent,false); + StationViewHolder viewHolder = new StationViewHolder(view); + return viewHolder; + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + BusPassengerStation station = mStations.get(position); + StationViewHolder viewHolder = (StationViewHolder)holder; + viewHolder.stationName.setText(station.getName()); + BlinkAnimationUtil.clearAnimation(viewHolder.stationCircle); + if (position == 0){ //第一个 起点 + viewHolder.stationTagTxt.setText("起"); + viewHolder.stationStationTag.setBackground(mContext.getDrawable(R.drawable.bg_bus_p_start_tag_bg)); + viewHolder.groupStationTagPanel.setVisibility(View.VISIBLE); + viewHolder.curArrowBg.setVisibility(View.GONE); + if (station.getDrivingStatus() == STATION_STATUS_STOPPED && !station.isLeaving()){//到达未离开 + 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){ + viewHolder.stationTagTxt.setText("终"); + viewHolder.stationStationTag.setBackground(mContext.getDrawable(R.drawable.bg_bus_p_end_tag_bg)); + viewHolder.groupStationTagPanel.setVisibility(View.VISIBLE); + }else { + viewHolder.groupStationTagPanel.setVisibility(View.GONE); + } + viewHolder.curArrowBg.setVisibility(View.VISIBLE); + BusPassengerStation preStation = mStations.get(position -1); + if (station.getDrivingStatus() == STATION_STATUS_LEAVING || + (station.getDrivingStatus() == STATION_STATUS_STOPPED && station.isLeaving())){ //过站 + 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); + } + } + } + + @Override + public int getItemCount() { + return mStations.size(); + } +} +class StationViewHolder extends RecyclerView.ViewHolder{ + public MarqueeTextView stationName; + public ImageView stationCircle; + public ImageView curArrowBg; + public ImageView stationStationTag; + public TextView stationTagTxt; + public Group groupStationTagPanel; + public StationViewHolder(@NonNull View itemView) { + super(itemView); + stationName = itemView.findViewById(R.id.bus_p_station); + stationCircle = itemView.findViewById(R.id.bus_p_circle); + curArrowBg = itemView.findViewById(R.id.bus_p_cur_arrow_bg); + stationStationTag = itemView.findViewById(R.id.bus_p_tag); + stationTagTxt = itemView.findViewById(R.id.bus_p_tag_txt); + groupStationTagPanel = itemView.findViewById(R.id.group_station_tag_panel); + } +} + + diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/bean/BusPassengerOperationStatusResponse.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/bean/BusPassengerOperationStatusResponse.java new file mode 100644 index 0000000000..c559d22368 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/bean/BusPassengerOperationStatusResponse.java @@ -0,0 +1,21 @@ +package com.mogo.och.bus.passenger.bean; + +import com.mogo.eagle.core.data.BaseData; + +/** + * @author congtaowang + * @since 2021/3/22 + * + * 小巴车运营状态返回参数 + */ +public class BusPassengerOperationStatusResponse extends BaseData { + + public Result data; + + public static class Result { + private String sn; //司机屏sn + private String phone; //司机手机号 + public String plateNumber; //车牌号 + public int driverStatus;//0:已收车,1:已出车 + } +} diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/bean/BusPassengerQueryLineRequest.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/bean/BusPassengerQueryLineRequest.java new file mode 100644 index 0000000000..35ba94ce3a --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/bean/BusPassengerQueryLineRequest.java @@ -0,0 +1,16 @@ +package com.mogo.och.bus.passenger.bean; + +public +/** + * @author congtaowang + * @since 2021/3/22 + * + * 根据车机行驶线路站点信息 + */ +class BusPassengerQueryLineRequest { + + private String sn; + public BusPassengerQueryLineRequest(String sn) { + this.sn = sn; + } +} diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/bean/BusPassengerRoutesResponse.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/bean/BusPassengerRoutesResponse.java new file mode 100644 index 0000000000..01163fd6c5 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/bean/BusPassengerRoutesResponse.java @@ -0,0 +1,28 @@ +package com.mogo.och.bus.passenger.bean; + +import com.mogo.eagle.core.data.BaseData; + +/** + * 网约车小巴路线接口请求响应结果 返回的是对应司机屏的线路信息 + * + * @author tongchenfei + */ +public class BusPassengerRoutesResponse extends BaseData { + private BusPassengerRoutesResult data; + + public BusPassengerRoutesResult getResult() { + return data; + } + + public void setResult(BusPassengerRoutesResult data) { + this.data = data; + } + + @Override + public String toString() { + return "OchBusRoutesResponse{" + + "data=" + data + + '}'; + } + +} diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/bean/BusPassengerRoutesResult.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/bean/BusPassengerRoutesResult.java new file mode 100644 index 0000000000..602c549f85 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/bean/BusPassengerRoutesResult.java @@ -0,0 +1,79 @@ +package com.mogo.och.bus.passenger.bean; + +import java.util.List; +import java.util.Objects; + +/** + * 网约车小巴路线接口返回接口数据封装 + * + * @author tongchenfei + */ +public class BusPassengerRoutesResult { + private List sites; + private int lineId; + private String name; //线路名称 + private int lineType; //线路类型,0:环形 + private String description; + private int status; + private String runningDur; //运营时间 + private long taskTime; //线路时间班次 + + public List getSites() { + return sites; + } + + public int getLineId() { + return lineId; + } + + public String getName() { + return name; + } + + public int getLineType() { + return lineType; + } + + public String getDescription() { + return description; + } + + public int getStatus() { + return status; + } + + public String getRunningDur() { + return runningDur; + } + + @Override + public String toString() { + return "BusPassengerRoutesResult{" + + "sites=" + sites + + ", lineId=" + lineId + + ", name='" + name + '\'' + + ", lineType=" + lineType + + ", description='" + description + '\'' + + ", status=" + status + + ", runningDur='" + runningDur + '\'' + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + BusPassengerRoutesResult that = (BusPassengerRoutesResult) o; + return lineId == that.lineId + && lineType == that.lineType + && status == that.status + && sites.equals(that.sites) + && name.equals(that.name) + && runningDur.equals(that.runningDur); + } + + @Override + public int hashCode() { + return Objects.hash(sites, lineId, name, lineType, description, status, runningDur); + } +} diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/bean/BusPassengerStation.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/bean/BusPassengerStation.java new file mode 100644 index 0000000000..401bcd9dd1 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/bean/BusPassengerStation.java @@ -0,0 +1,173 @@ +package com.mogo.och.bus.passenger.bean; + +import java.util.Objects; + +/** + * 单个网约车小巴车站信息 + * + * @author wangmingjun + */ +public class BusPassengerStation { + + private String name; + private String description; + private String cityCode; + private double lon; //高精坐标 + private double lat; //高精坐标 + private double gcjLon; //高德坐标 + private double gcjLat; //高德坐标 + private int businessType; //站点类型,9:taxi,10:bus + 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 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 double getGcjLon() { + return gcjLon; + } + + public double getGcjLat() { + return gcjLat; + } + + 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 "OchBusStation{" + + "name='" + name + '\'' + + ", description='" + description + '\'' + + ", cityCode='" + cityCode + '\'' + + ", lon=" + lon + + ", lat=" + lat + + ", businessType=" + businessType + + ", status=" + status + + ", siteId=" + siteId + + ", seq=" + seq + + ", drivingStatus=" + drivingStatus + + ", ifStop=" + ifStop + + ", leaving=" + leaving + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + BusPassengerStation that = (BusPassengerStation) o; + return Double.compare(that.lon, lon) == 0 + && Double.compare(that.lat, lat) == 0 + && Double.compare(that.gcjLon, gcjLon) == 0 + && Double.compare(that.gcjLat, gcjLat) == 0 + && businessType == that.businessType + && status == that.status + && siteId == that.siteId + && seq == that.seq + && drivingStatus == that.drivingStatus + && ifStop == that.ifStop + && leaving == that.leaving + && Objects.equals(name, that.name) + && Objects.equals(cityCode, that.cityCode); + } + + @Override + public int hashCode() { + return Objects.hash(name, description, cityCode, lon, lat, gcjLon, gcjLat, businessType, status, siteId, seq, drivingStatus, ifStop, leaving); + } +} diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassegerDriverStatusCallback.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassegerDriverStatusCallback.java new file mode 100644 index 0000000000..06885b74ab --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassegerDriverStatusCallback.java @@ -0,0 +1,10 @@ +package com.mogo.och.bus.passenger.callback; + +/** + * @author: wangmingjun + * @date: 2021/10/22 + */ +public interface IBusPassegerDriverStatusCallback { + void changeOperationStatus(boolean changeStatus); + void updatePlateNumber(String plateNumber); +} diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassengerADASStatusCallback.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassengerADASStatusCallback.java new file mode 100644 index 0000000000..4dbf53010c --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassengerADASStatusCallback.java @@ -0,0 +1,20 @@ +package com.mogo.och.bus.passenger.callback; + +/** + * Created on 2022/3/31 + * + * Model->Presenter回调:ADAS相关(自动驾驶状态回调,到达终点等等) + */ +public interface IBusPassengerADASStatusCallback { + // 自动驾驶触发的已到达目的地:暂未用到 + void onAutopilotArriveEnd(); + + // 自动驾驶可用状态 + void onAutopilotEnable(); + + // 自动驾驶不可用状态 + void onAutopilotDisable(); + + // 自动驾驶运行中 + void onAutopilotRunning(); +} diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassengerAutopilotPlanningCallback.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassengerAutopilotPlanningCallback.java new file mode 100644 index 0000000000..786264650f --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassengerAutopilotPlanningCallback.java @@ -0,0 +1,16 @@ +package com.mogo.och.bus.passenger.callback; + +import com.amap.api.maps.model.LatLng; + +import java.util.List; + +import mogo.telematics.pad.MessagePad; + +/** + * Created on 2022/3/31 + */ +public interface IBusPassengerAutopilotPlanningCallback { + void routeResult(List models,int haveArrivedIndex); + void routePlanningToNextStationChanged(long meters, long timeInSecond); + void updateTotalDistance(); +} diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassengerControllerStatusCallback.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassengerControllerStatusCallback.java new file mode 100644 index 0000000000..cc0bc3f4c7 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassengerControllerStatusCallback.java @@ -0,0 +1,15 @@ +package com.mogo.och.bus.passenger.callback; + +import com.mogo.eagle.core.data.map.MogoLocation; + +/** + * Created on 2022/3/31 + * + * Model->Presenter回调:状态控制器监听(accOn、adas ui show、voice ui show、push ui show、v2x ui show等等) + */ +public interface IBusPassengerControllerStatusCallback { + // 是否vr map模式 + void onVRModeChanged(boolean isVRMode); + // 自车定位 + void onCarLocationChanged(MogoLocation location); +} diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassengerMapViewCallback.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassengerMapViewCallback.java new file mode 100644 index 0000000000..25f7d3bbec --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassengerMapViewCallback.java @@ -0,0 +1,9 @@ +package com.mogo.och.bus.passenger.callback; + +/** + * @author: wangmingjun + * @date: 2022/3/10 + */ +public interface IBusPassengerMapViewCallback { + void onCameraChange(float bearing); +} diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassengerRouteLineInfoCallback.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassengerRouteLineInfoCallback.java new file mode 100644 index 0000000000..b7d348a2b2 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/callback/IBusPassengerRouteLineInfoCallback.java @@ -0,0 +1,16 @@ +package com.mogo.och.bus.passenger.callback; + +import com.mogo.och.bus.passenger.bean.BusPassengerStation; + +import java.util.List; + +/** + * @author: wangmingjun + * @date: 2022/4/6 + */ +public interface IBusPassengerRouteLineInfoCallback { + void updateLineInfo(String lineName, String lineDurTime); + void updateStationsInfo(List stations, int currentStationIndex, boolean isArrived); + void showNoTaskView(); + void hideNoTaskView(); +} diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/model/BusPassengerModel.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/model/BusPassengerModel.java new file mode 100644 index 0000000000..3e013fef4f --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/model/BusPassengerModel.java @@ -0,0 +1,580 @@ +package com.mogo.och.bus.passenger.model; + +import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS_P; +import static com.mogo.och.bus.passenger.constant.BusPassengerConst.QUERY_BUS_P_STATION_DELAY; +import static com.mogo.och.bus.passenger.constant.BusPassengerConst.STATION_STATUS_STOPPED; + +import android.content.Context; +import android.content.Intent; +import android.net.ConnectivityManager; +import android.os.Handler; +import android.os.Message; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.amap.api.maps.model.LatLng; +import com.mogo.aicloud.services.socket.MogoAiCloudSocketManager; +import com.mogo.commons.debug.DebugConfig; +import com.mogo.commons.module.intent.IMogoIntentListener; +import com.mogo.commons.module.intent.IntentManager; +import com.mogo.commons.module.status.IMogoStatusChangedListener; +import com.mogo.commons.module.status.MogoStatusManager; +import com.mogo.commons.module.status.StatusDescriptor; +import com.mogo.eagle.core.data.autopilot.AutopilotStatusInfo; +import com.mogo.eagle.core.data.config.FunctionBuildConfig; +import com.mogo.eagle.core.data.map.MogoLocation; +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener; +import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener; +import com.mogo.eagle.core.function.api.autopilot.IMoGoPlanningRottingListener; +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager; +import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager; +import com.mogo.eagle.core.function.call.autopilot.CallerPlanningRottingListenerManager; +import com.mogo.eagle.core.network.utils.GsonUtil; +import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr; +import com.mogo.eagle.core.utilcode.util.CoordinateUtils; +import com.mogo.eagle.core.utilcode.util.NetworkUtils; +import com.mogo.eagle.core.utilcode.util.ToastUtils; +import com.mogo.och.bus.passenger.R; +import com.mogo.och.bus.passenger.bean.BusPassengerOperationStatusResponse; +import com.mogo.och.bus.passenger.bean.BusPassengerRoutesResponse; +import com.mogo.och.bus.passenger.bean.BusPassengerRoutesResult; +import com.mogo.och.bus.passenger.bean.BusPassengerStation; +import com.mogo.och.bus.passenger.callback.IBusPassegerDriverStatusCallback; +import com.mogo.och.bus.passenger.callback.IBusPassengerADASStatusCallback; +import com.mogo.och.bus.passenger.callback.IBusPassengerAutopilotPlanningCallback; +import com.mogo.och.bus.passenger.callback.IBusPassengerControllerStatusCallback; +import com.mogo.och.bus.passenger.callback.IBusPassengerRouteLineInfoCallback; +import com.mogo.och.bus.passenger.constant.BusPassengerConst; +import com.mogo.och.bus.passenger.network.BusPassengerModelLoopManager; +import com.mogo.och.bus.passenger.network.BusPassengerServiceManager; +import com.mogo.och.common.module.biz.network.OchCommonServiceCallback; +import com.mogo.och.common.module.manager.AbnormalFactorsLoopManager; +import com.mogo.och.common.module.utils.CoordinateCalculateRouteUtil; + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import mogo.telematics.pad.MessagePad; +import mogo_msg.MogoReportMsg; +import system_master.SystemStatusInfo; + +/** + * Created on 2022/3/31 + */ +public class BusPassengerModel { + private static final String TAG = BusPassengerModel.class.getSimpleName(); + + private List mRoutePoints = new ArrayList<>(); + + private static final class SingletonHolder { + private static final BusPassengerModel INSTANCE = new BusPassengerModel(); + } + + public static BusPassengerModel getInstance() { + return SingletonHolder.INSTANCE; + } + + private Context mContext; + private IBusPassengerADASStatusCallback mADASStatusCallback; //Model->Presenter:自动驾驶状态相关 + private IBusPassengerAutopilotPlanningCallback mAutopilotPlanningCallback; //Model->Presenter:自动驾驶线路规划 + private Map mControllerStatusCallbackMap = new ConcurrentHashMap<>(); + + private IBusPassegerDriverStatusCallback mDriverStatusCallback; //出车收车状态 + private IBusPassengerRouteLineInfoCallback mRouteLineInfoCallback; // bus路线信息更新 + + private MogoLocation mLocation = null; + + private BusPassengerRoutesResult routesResult = null; + + List mStations = new ArrayList<>(); + private int mNextStationIndex = 0;// 要到达站的index + private List mTwoStationsRouts = new ArrayList<>(); + private int mPreRouteIndex = 0; + private int mWipePreIndex = 0; + + private static final int MSG_QUERY_BUS_P_STATION = 1001; + private final Handler handler = new Handler(new Handler.Callback() { + @Override + public boolean handleMessage(Message msg) { + if ( msg.what == MSG_QUERY_BUS_P_STATION ) { + queryDriverOperationStatus(); + return true; + } + return false; + } + }); + + private BusPassengerModel() { + } + + public void init( Context context ) { + mContext = context.getApplicationContext(); + initListeners(); + // TODO: 2022/3/31 + queryDriverOperationStatus(); + startOrStopOrderLoop(true); + } + + public void setDriverStatusCallback(IBusPassegerDriverStatusCallback callback){ + this.mDriverStatusCallback = callback; + } + + public void setRouteLineInfoCallback(IBusPassengerRouteLineInfoCallback callback){ + this.mRouteLineInfoCallback = callback; + } + + private void queryDriverOperationDelay() { + handler.sendEmptyMessageDelayed( MSG_QUERY_BUS_P_STATION, QUERY_BUS_P_STATION_DELAY ); + } + + private void queryDriverOperationStatus() { + BusPassengerServiceManager.queryDriverOperationStatus(mContext + , new OchCommonServiceCallback() { + @Override + public void onSuccess(BusPassengerOperationStatusResponse data) { + if (data == null || data.data == null) return; + if (mDriverStatusCallback != null) { + CallerLogger.INSTANCE.d( M_BUS_P + TAG, "queryDriverOperationStatus = %s", data.data.plateNumber ); + mDriverStatusCallback.changeOperationStatus(data.data.driverStatus == 1); + mDriverStatusCallback.updatePlateNumber(data.data.plateNumber); + } + } + + @Override + public void onError() { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort(mContext.getString(R.string.network_error_tip)); + } else { + ToastUtils.showShort(mContext.getString(R.string.request_error_tip)); + } + queryDriverOperationDelay(); + } + + @Override + public void onFail(int code, String msg) { + //延迟3s再次查询 + queryDriverOperationDelay(); + } + }); + } + + public void queryDriverSiteByCoordinate(){ + BusPassengerServiceManager.queryDriverSiteByCoordinate(mContext + , new OchCommonServiceCallback() { + @Override + public void onSuccess(BusPassengerRoutesResponse data) { + if ( data == null || data.getResult() == null) { + CallerLogger.INSTANCE.d( M_BUS_P + TAG, "queryDriverSiteByCoordinate = null"); + if (routesResult != null) { + routesResult = null; + mNextStationIndex = 0; + startOrStopCalculateRouteInfo(false); + if (mRouteLineInfoCallback != null){ + mRouteLineInfoCallback.showNoTaskView(); + } + } + + return; + } + if (routesResult != null && data.getResult().equals(routesResult)){ + CallerLogger.INSTANCE.d( M_BUS_P + TAG, "queryDriverSiteByCoordinate = not update"); + return; + } + routesResult = data.getResult(); + updatePassengerRouteInfo(data.getResult()); + } + + @Override + public void onFail(int code, String msg) { + CallerLogger.INSTANCE.d( M_BUS_P + TAG, "queryDriverSiteByCoordinate = %s", msg + + ", sn = " +BusPassengerServiceManager.INSTANCE.getDriverAppSn()); + if (code == 1003){ + queryDriverOperationDelay(); + } + if (BusPassengerServiceManager.INSTANCE.getDriverAppSn().isEmpty()){ + //此处拦截是为了防止过程中乘客屏和司机端断连,拿不到司机端sn, 造成请求失败去刷新了界面 + return; + } + if (code == 1003){ + routesResult = null; + startOrStopCalculateRouteInfo(false); + return; + } + } + }); + } + + private void updatePassengerRouteInfo(BusPassengerRoutesResult result) { + if (mRouteLineInfoCallback != null){ + mRouteLineInfoCallback.updateLineInfo(result.getName(),result.getRunningDur()); + mRouteLineInfoCallback.hideNoTaskView(); + if (result.getSites() != null){ + List stations = result.getSites(); + mStations.clear(); + mStations.addAll(stations); + for (int i = 0; i< stations.size(); i++){ + BusPassengerStation station = stations.get(i); + if (station.getDrivingStatus() == STATION_STATUS_STOPPED && station.isLeaving() && i+1 < stations.size()){ + mRouteLineInfoCallback.updateStationsInfo(stations,i+1,false); + if(mNextStationIndex != i+1){ + mTwoStationsRouts.clear(); + startRemainRouteInfo(); + } + mNextStationIndex = i+1; + return; + }else if (station.getDrivingStatus() == STATION_STATUS_STOPPED && !station.isLeaving()){ + if (i == 0){ + startOrStopRouteAndWipe(false); + } + mPreRouteIndex = 0; + startOrStopCalculateRouteInfo(false); + mRouteLineInfoCallback.updateStationsInfo(stations,i,true); + return; + } + } + } + } + + } + + public void release() { + releaseListeners(); + startOrStopCalculateRouteInfo(false); + startOrStopOrderLoop(false); + } + + public void setMoGoAutopilotPlanningListener(IBusPassengerAutopilotPlanningCallback + moGoAutopilotPlanningCallback) { + this.mAutopilotPlanningCallback = moGoAutopilotPlanningCallback; + } + + public void setADASStatusCallback(IBusPassengerADASStatusCallback callback) { + this.mADASStatusCallback = callback; + } + + public void setControllerStatusCallback(String tag, IBusPassengerControllerStatusCallback callback) { + if (tag == null || "".equals(tag)) return; + + if (callback == null) { + mControllerStatusCallbackMap.remove(tag); + return; + } + + mControllerStatusCallbackMap.put(tag,callback); + + } + + private void initListeners() { + + // 2021.11.1重构自动驾驶 实现接口 IMoGoAutopilotStatusListener 注册监听 替换IMogoAdasOCHCallback接口 + CallerAutoPilotStatusListenerManager.INSTANCE.addListener(TAG, mGoAutopilotStatusListener); + IntentManager.getInstance().registerIntentListener(ConnectivityManager.CONNECTIVITY_ACTION, mNetWorkIntentListener ); + MogoStatusManager.getInstance().registerStatusChangedListener(TAG, StatusDescriptor.VR_MODE, mMogoStatusChangedListener ); + // 定位监听 + CallerChassisLocationGCJ02ListenerManager.INSTANCE.addListener(TAG, mMapLocationListener); + + //2021.11.1 自动驾驶路线规划接口 + CallerPlanningRottingListenerManager.INSTANCE.addListener(TAG,moGoAutopilotPlanningListener); + + AbnormalFactorsLoopManager.INSTANCE.startLoopAbnormalFactors(mContext); + } + + private void releaseListeners() { + MogoStatusManager.getInstance().unregisterStatusChangedListener(TAG, StatusDescriptor.VR_MODE, mMogoStatusChangedListener); + + // 注销定位监听 + CallerChassisLocationGCJ02ListenerManager.INSTANCE.removeListener(TAG); + + MogoAiCloudSocketManager.getInstance(mContext) + .unregisterLifecycleListener(10010); + + CallerAutoPilotStatusListenerManager.INSTANCE.removeListener(mGoAutopilotStatusListener); + CallerPlanningRottingListenerManager.INSTANCE.removeListener(moGoAutopilotPlanningListener); + + AbnormalFactorsLoopManager.INSTANCE.stopLoopAbnormalFactors(); + } + + //监听网络变化,避免启动机器时无网导致无法更新订单信息 + private final IMogoIntentListener mNetWorkIntentListener = new IMogoIntentListener() { + @Override + public void onIntentReceived( String intentStr, Intent intent ) { + CallerLogger.INSTANCE.d( M_BUS_P + TAG, "onIntentReceived = %s", intentStr ); + if ( ConnectivityManager.CONNECTIVITY_ACTION.equals( intentStr ) ) { + if ( NetworkUtils.isConnected( mContext ) ) { + queryDriverOperationStatus(); + } + } + } + }; + + // VR mode变更回调 + private final IMogoStatusChangedListener mMogoStatusChangedListener = (descriptor, isTrue) -> { + if (StatusDescriptor.VR_MODE == descriptor) { + if (mControllerStatusCallbackMap.size() > 0) { + for (IBusPassengerControllerStatusCallback callback :mControllerStatusCallbackMap.values()){ + callback.onVRModeChanged(isTrue); + } + } + } + }; + + private final IMoGoChassisLocationGCJ02Listener mMapLocationListener = new IMoGoChassisLocationGCJ02Listener() { + @Override + public void onChassisLocationGCJ02(@Nullable MogoLocation gnssInfo) { + if (null == gnssInfo) return; + mLocation = gnssInfo; + for (IBusPassengerControllerStatusCallback callback :mControllerStatusCallbackMap.values()){ + callback.onCarLocationChanged(gnssInfo); + } + } + }; + + private volatile int mPreAutoStatus = -1; + + private final IMoGoAutopilotStatusListener mGoAutopilotStatusListener = new IMoGoAutopilotStatusListener(){ + + @Override + public void onAutopilotRouteLineId(long lineId) { + + } + + @Override + public void onAutopilotIpcConnectStatusChanged(int status, @Nullable String reason) { + } + + @Override + public void onAutopilotGuardian(@Nullable MogoReportMsg.MogoReportMessage guardianInfo) { + + } + + private boolean arriveAtEnd = false; //乘客app专用字段 + + @Override + public void onAutopilotStatusResponse(@NotNull AutopilotStatusInfo autopilotStatusInfo) { + if (autopilotStatusInfo == null) return; + int state = autopilotStatusInfo.getState(); + if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) { + //2022.7.20 自动驾驶更换成带档位的 +// if (mADASStatusCallback != null) mADASStatusCallback.onAutopilotRunning(); + } else if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE) { + if(state != mPreAutoStatus){ + mTwoStationsRouts.clear(); + } +// if (mADASStatusCallback != null) mADASStatusCallback.onAutopilotEnable(); + } else if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE) { + if(state != mPreAutoStatus){ + mTwoStationsRouts.clear(); + } +// if (mADASStatusCallback != null) mADASStatusCallback.onAutopilotDisable(); + }else if (state == IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING){ + if(state != mPreAutoStatus){ + mTwoStationsRouts.clear(); + } + } + mPreAutoStatus = state; + } + + @Override + public void onAutopilotSNRequest() { + + } + + @Override + public void onAutopilotArriveAtStation(@Nullable MessagePad.ArrivalNotification arrivalNotification) { + if (FunctionBuildConfig.isDemoMode + && AppIdentityModeUtils.isPassenger(FunctionBuildConfig.appIdentityMode)) { + arriveAtEnd = true; + } + + // TODO: 2022/3/31 + if (DebugConfig.isDebug()) { + // ToastUtils.showShort("到达目的地"); + } + if (mADASStatusCallback != null){ + mADASStatusCallback.onAutopilotArriveEnd(); + } + } + + @Override + public void onAutopilotStatusRespByQuery(@NonNull SystemStatusInfo.StatusInfo status) { + + } + }; + + private final IMoGoPlanningRottingListener moGoAutopilotPlanningListener = new IMoGoPlanningRottingListener(){ + + @Override + public void onAutopilotRotting(@Nullable MessagePad.GlobalPathResp routeList) { + CallerLogger.INSTANCE.d(M_BUS_P + TAG, "onAutopilotRotting = " + + GsonUtil.jsonFromObject(routeList)); + List routePoints = routeList.getWayPointsList(); + if (null != routePoints && routePoints.size() > 0){ + updateRoutePoints(routePoints); + startToRouteAndWipe(); + } + } + }; + + public void updateRoutePoints(List routePoints){ + mRoutePoints.clear(); + List latLngModels = CoordinateCalculateRouteUtil + .coordinateConverterWgsToGcjLocations(mContext,routePoints); + mRoutePoints.addAll(latLngModels); + calculateTwoStationsRoute(); + } + + private void calculateTwoStationsRoute(){ + //找出前往站对应的轨迹点,拿出两站点的集合 + CallerLogger.INSTANCE.d(M_BUS_P + TAG, "mRoutePoints.size() = " + mRoutePoints.size()); + if (mRoutePoints.size() > 0) { + if (mStations.size() > 1){ //两个站点及以上要计算两个站点间的轨迹路线 + if (mNextStationIndex <= mStations.size()-1 && mNextStationIndex - 1 >=0){ + mTwoStationsRouts.clear(); + BusPassengerStation stationNext = mStations.get(mNextStationIndex); + BusPassengerStation stationCur = mStations.get(mNextStationIndex - 1); + //当前站在轨迹中对应的点 + int currentRouteIndex = CoordinateCalculateRouteUtil.getArrivedPointIndexNew(0 + ,mRoutePoints + ,stationCur.getGcjLon(),stationCur.getGcjLat()); + //要前往的站在轨迹中对应的点 + int nextRouteIndex = CoordinateCalculateRouteUtil.getArrivedPointIndexNew(currentRouteIndex + ,mRoutePoints + ,stationNext.getGcjLon(),stationNext.getGcjLat()); + CallerLogger.INSTANCE.d(M_BUS_P + TAG, "轨迹排查==currentRouteIndex = " + currentRouteIndex + + ", nextRouteIndex = " + nextRouteIndex); + if (currentRouteIndex < nextRouteIndex){ //如果找到的next在起点的轨迹前面,直接舍弃这个轨迹,不显示 + mTwoStationsRouts.addAll(mRoutePoints.subList(currentRouteIndex,nextRouteIndex + 1)); + } + } + } +// else { //只有两个站点的时候整个路线就是两个站点之间的轨迹 +// mTwoStationsRouts.clear(); +// mTwoStationsRouts.addAll(mRoutePoints); +// } + if (mTwoStationsRouts.size() > 0){ + float sumLength = CoordinateCalculateRouteUtil.calculateRouteSumLength(mTwoStationsRouts); + SharedPrefsMgr.getInstance(mContext).putInt(BusPassengerConst.BUS_SP_KEY_ORDER_SUM_DIS,(int) sumLength); + if (mAutopilotPlanningCallback != null){ + mAutopilotPlanningCallback.updateTotalDistance(); + } + } + } + } + + public void dynamicCalculateRouteInfo() { + //计算当前位置和下一站的剩余点集合 + //计算剩余点总里程和时间 + if (mTwoStationsRouts.size() == 0){ + calculateTwoStationsRoute(); + } + if (mTwoStationsRouts.size() > 0 && mLocation != null){ + Map> lastPointsMap = CoordinateCalculateRouteUtil + .getRemainPointListByCompareNew(mPreRouteIndex,mTwoStationsRouts,mLocation); + for (int index: lastPointsMap.keySet()) { + mPreRouteIndex = index; + break; + } + + for (List lastPoints: lastPointsMap.values()){ + CallerLogger.INSTANCE.d(M_BUS_P + TAG, "轨迹排查==lastPoints.size() = " + lastPoints.size()); + float lastSumLength = 0; + if (lastPoints.size() == 1){ //只是最后一个点,计算当前位置和最后一个点的距离 + if (mNextStationIndex <= mStations.size()-1 && mNextStationIndex >= 0){ + BusPassengerStation stationNext = mStations.get(mNextStationIndex); + lastSumLength = CoordinateUtils.calculateLineDistance( + stationNext.getGcjLon(), stationNext.getGcjLat(), + mLocation.getLongitude(), mLocation.getLatitude()); + }else { + lastSumLength = CoordinateUtils.calculateLineDistance( + lastPoints.get(0).getLongitude(), lastPoints.get(0).getLatitude(), + mLocation.getLongitude(), mLocation.getLatitude()); + } + + }else { + lastSumLength = CoordinateCalculateRouteUtil.calculateRouteSumLength(lastPoints); + } + + double lastTime = lastSumLength / getAverageSpeed() * 3.6 ; //秒 + CallerLogger.INSTANCE.d(M_BUS_P + TAG, "轨迹排查==lastSumLength = " + lastSumLength); + if (mAutopilotPlanningCallback != null){ + mAutopilotPlanningCallback.routePlanningToNextStationChanged((long)lastSumLength,(long) lastTime); + } + } + } + } + + public int getAverageSpeed(){ + return BusPassengerConst.SHUTTLE_AVERAGE_SPEED; + } + + public void startRemainRouteInfo() { + //开启实时计算剩余距离,剩余时间,预计时间 + startOrStopCalculateRouteInfo(true); + } + + public void startToRouteAndWipe() { + startOrStopRouteAndWipe(true); + } + + /** + * 实时轨迹擦除 + * @param isStart + */ + public void startOrStopRouteAndWipe(boolean isStart){ + if (isStart){ + BusPassengerModelLoopManager.getInstance().startOrStopRouteAndWipe(); + }else { + mWipePreIndex = 0; + BusPassengerModelLoopManager.getInstance().stopOrStopRouteAndWipe(); + } + } + + public void loopRouteAndWipe() { + if (mRoutePoints != null && mRoutePoints.size() > 0 && mLocation != null){ + int haveArrivedIndex = CoordinateCalculateRouteUtil + .getArrivedPointIndexNew(mWipePreIndex, + mRoutePoints, + mLocation); + + mWipePreIndex = haveArrivedIndex; + + CallerLogger.INSTANCE.d(M_BUS_P + TAG, "thread = "+ Thread.currentThread().getName()+" haveArrivedIndex== " + haveArrivedIndex); + if (mAutopilotPlanningCallback != null){ + List routePoints = CoordinateCalculateRouteUtil + .coordinateConverterLocationToLatLng(mContext,mRoutePoints); + mAutopilotPlanningCallback.routeResult(routePoints,haveArrivedIndex); + } + } + } + + /** + * 开始轮询计算剩余里程和时间 + * @param isStart + */ + public void startOrStopCalculateRouteInfo(boolean isStart) { + CallerLogger.INSTANCE.d(M_BUS_P + TAG, "startOrStopCalculateRouteInfo() " + isStart); + if (isStart) { + BusPassengerModelLoopManager.getInstance().startCalculateRouteInfoLoop(); + } else { + mTwoStationsRouts.clear(); + BusPassengerModelLoopManager.getInstance().stopCalculateRouteInfLoop(); + } + } + + private void startOrStopOrderLoop(boolean start) { + CallerLogger.INSTANCE.d(M_BUS_P + TAG, "startOrStopOrderLoop() " + start); + if (start) { + BusPassengerModelLoopManager.getInstance().startQueryDriverLineLoop(); + } else { + BusPassengerModelLoopManager.getInstance().stopQueryDriverLineLoop(); + } + } + +} diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/network/BusPassengerModelLoopManager.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/network/BusPassengerModelLoopManager.java new file mode 100644 index 0000000000..c0d1db411d --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/network/BusPassengerModelLoopManager.java @@ -0,0 +1,160 @@ +package com.mogo.och.bus.passenger.network; + +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.och.bus.passenger.model.BusPassengerModel; + +import java.util.concurrent.TimeUnit; + +import io.reactivex.Observable; +import io.reactivex.ObservableEmitter; +import io.reactivex.ObservableOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Consumer; +import io.reactivex.schedulers.Schedulers; + +import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS_P; +import static com.mogo.och.bus.passenger.constant.BusPassengerConst.LOOP_DELAY; +import static com.mogo.och.bus.passenger.constant.BusPassengerConst.LOOP_LINE_2S; +import static com.mogo.och.bus.passenger.constant.BusPassengerConst.LOOP_LINE_1S; + +/** + * Created on 2021/11/22 + * + * 管理轮询逻辑(订单轮询、新单轮询、新单抢单结果轮询等等) + */ +public class BusPassengerModelLoopManager { + + private static final String TAG = BusPassengerModelLoopManager.class.getSimpleName(); + + private static final class SingletonHolder { + private static final BusPassengerModelLoopManager INSTANCE = new BusPassengerModelLoopManager(); + } + + public static BusPassengerModelLoopManager getInstance() { + return SingletonHolder.INSTANCE; + } + + private Disposable mQueryLineDisposable; //心跳轮询 + private CompositeDisposable mRouteWipeDisposable; + private CompositeDisposable mCalculateRouteDisposable; //每隔2s计算一次剩余里程和时间 + + public void startOrStopRouteAndWipe() { + CallerLogger.INSTANCE.i(M_BUS_P + TAG, "startOrStopRouteWipe()"); + if (mRouteWipeDisposable != null) return; + if (mRouteWipeDisposable == null){ + mRouteWipeDisposable = new CompositeDisposable(); + } + Disposable disposable = startLoopRouteAndWipe() + .doOnSubscribe(new Consumer() { + @Override + public void accept(Disposable disposable) throws Exception { + } + }) + .doOnError(new Consumer() { + @Override + public void accept(Throwable throwable) throws Exception { + } + }) + .delay(LOOP_LINE_1S, TimeUnit.MILLISECONDS, true) // 设置delayError为true,表示出现错误的时候也需要延迟5s进行通知,达到无论是请求正常还是请求失败,都是5s后重新订阅,即重新请求。 + .subscribeOn(Schedulers.io()) + .repeat() // repeat保证请求成功后能够重新订阅。 + .retry() // retry保证请求失败后能重新订阅 + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Consumer() { + @Override + public void accept(Integer integer) throws Exception { + } + }); + mRouteWipeDisposable.add(disposable); + } + + public void stopOrStopRouteAndWipe() { + if (mRouteWipeDisposable != null) { + mRouteWipeDisposable.dispose(); + mRouteWipeDisposable = null; + } + } + + public void startQueryDriverLineLoop() { + if (mQueryLineDisposable != null && !mQueryLineDisposable.isDisposed()) { + return; + } + CallerLogger.INSTANCE.i(M_BUS_P + TAG, "startQueryDriverLineLoop()"); + mQueryLineDisposable = Observable.interval(LOOP_DELAY, + LOOP_LINE_2S, TimeUnit.MILLISECONDS) + .map((aLong -> aLong + 1)) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(aLong -> BusPassengerModel.getInstance().queryDriverSiteByCoordinate()); + } + + public void stopQueryDriverLineLoop() { + if (mQueryLineDisposable != null) { + CallerLogger.INSTANCE.i(M_BUS_P + TAG, "stopQueryDriverLineLoop()"); + mQueryLineDisposable.dispose(); + mQueryLineDisposable = null; + } + } + + public void startCalculateRouteInfoLoop() { + CallerLogger.INSTANCE.i(M_BUS_P + TAG, "startCalculateRouteInfoLoop()"); + if (mCalculateRouteDisposable != null) return; + if (mCalculateRouteDisposable == null){ + mCalculateRouteDisposable = new CompositeDisposable(); + } + Disposable disposable = startLoopCalculateRouteInfo() + .doOnSubscribe(new Consumer() { + @Override + public void accept(Disposable disposable) throws Exception { + } + }) + .doOnError(new Consumer() { + @Override + public void accept(Throwable throwable) throws Exception { + } + }) + .delay(LOOP_LINE_2S, TimeUnit.MILLISECONDS, true) // 设置delayError为true,表示出现错误的时候也需要延迟5s进行通知,达到无论是请求正常还是请求失败,都是5s后重新订阅,即重新请求。 + .subscribeOn(Schedulers.io()) + .repeat() // repeat保证请求成功后能够重新订阅。 + .retry() // retry保证请求失败后能重新订阅 + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Consumer() { + @Override + public void accept(Integer integer) throws Exception { + } + }); + mCalculateRouteDisposable.add(disposable); + } + + public void stopCalculateRouteInfLoop() { + if (mCalculateRouteDisposable != null) { + CallerLogger.INSTANCE.i(M_BUS_P + TAG, "stopCalculateRouteInfLoop()"); + mCalculateRouteDisposable.dispose(); + mCalculateRouteDisposable = null; + } + } + + private Observable startLoopRouteAndWipe(){ + return Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter emitter) throws Exception { + if (emitter.isDisposed()) return; + BusPassengerModel.getInstance().loopRouteAndWipe(); + emitter.onComplete(); + } + }); + } + + private Observable startLoopCalculateRouteInfo(){ + return Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter emitter) throws Exception { + if (emitter.isDisposed()) return; + BusPassengerModel.getInstance().dynamicCalculateRouteInfo(); + emitter.onComplete(); + } + }); + } +} diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/network/BusPassengerServiceManager.kt b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/network/BusPassengerServiceManager.kt new file mode 100644 index 0000000000..b868bd9994 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/network/BusPassengerServiceManager.kt @@ -0,0 +1,80 @@ +package com.mogo.och.bus.passenger.network + +import android.content.Context +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.eagle.core.data.config.FunctionBuildConfig +import com.mogo.eagle.core.function.call.telematic.CallerTelematicManager +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.eagle.core.utilcode.mogo.AppIdentityModeUtils +import com.mogo.och.bus.passenger.constant.URLConst.Companion.getBaseUrl +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.network.OchCommonSubscribeImpl +import com.mogo.och.common.module.biz.network.interceptor.transformTry + +/** + * Created on 2022/3/31 + */ +object BusPassengerServiceManager { + + private var driverSnCache = "" + + private var mShuttleBusPassengerServiceApi = + MoGoRetrofitFactory.getInstance(OchCommonConst.getShuttleUrl()).create(ShettlePassengerServiceApi::class.java) + + /** + * 获取Bus司机端的sn + * @return + */ + val driverAppSn: String + get() { + val serverToken = getServerToken() + if (serverToken != driverSnCache && serverToken.isNotEmpty()) { + driverSnCache = serverToken + } + return driverSnCache + } + + /** + * 查询绑定行驶的小巴车路线 + * @param context + * @param callback + */ + @JvmStatic + fun queryDriverSiteByCoordinate( + context: Context, callback: OchCommonServiceCallback? + ) { + mShuttleBusPassengerServiceApi.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? + ) { + mShuttleBusPassengerServiceApi.queryDriverOperationStatus( + MoGoAiCloudClientConfig.getInstance().serviceAppId, + MoGoAiCloudClientConfig.getInstance().token, + driverAppSn + ) + .transformTry() + .subscribe(OchCommonSubscribeImpl(context, callback, "queryDriverOperationStatus")) + + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/network/ShettlePassengerServiceApi.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/network/ShettlePassengerServiceApi.java new file mode 100644 index 0000000000..c780786bf2 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/network/ShettlePassengerServiceApi.java @@ -0,0 +1,40 @@ +package com.mogo.och.bus.passenger.network; + +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 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; + +/** + * Created on 2022/3/31 + * + * Bus乘客端接口定义 + */ +interface ShettlePassengerServiceApi { + /** + * 查询bus司机端绑定路线 + * @return 接口返回数据 + */ + @Headers( {"Content-Type:application/json;charset=UTF-8"} ) + @POST( "/och-shuttle-cabin/api/business/v1/passenger/lineDataWithDriver/query" ) + Observable queryDriverSiteByCoordinate(@Header("appId") String appId, @Header("ticket") String ticket, @Body BusPassengerQueryLineRequest request); + + /** + * 查询司机端的登陆状态 + * @param sn + * @return + */ + @Headers({"Content-type:application/json;charset=UTF-8"}) +// @GET("/autopilot-car-hailing/car/v2/driver/bus/passenger/takeOrderStatus/query") + @GET("/och-shuttle-cabin/api/business/v1/passenger/loginStatus") + Observable queryDriverOperationStatus(@Header ("appId") String appId, @Header("ticket") String ticket, @Query("sn") String sn); + + +} diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/presenter/BaseBusPassengerPresenter.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/presenter/BaseBusPassengerPresenter.java new file mode 100644 index 0000000000..0373dbc61b --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/presenter/BaseBusPassengerPresenter.java @@ -0,0 +1,164 @@ +package com.mogo.och.bus.passenger.presenter; + +import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS_P; + +import android.os.Looper; + +import androidx.annotation.NonNull; +import androidx.lifecycle.LifecycleOwner; + +import com.amap.api.maps.model.LatLng; +import com.mogo.commons.AbsMogoApplication; +import com.mogo.commons.mvp.Presenter; +import com.mogo.eagle.core.data.map.MogoLocation; +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.eagle.core.utilcode.util.UiThreadHandler; +import com.mogo.och.bus.passenger.bean.BusPassengerStation; +import com.mogo.och.bus.passenger.callback.IBusPassegerDriverStatusCallback; +import com.mogo.och.bus.passenger.callback.IBusPassengerADASStatusCallback; +import com.mogo.och.bus.passenger.callback.IBusPassengerAutopilotPlanningCallback; +import com.mogo.och.bus.passenger.callback.IBusPassengerControllerStatusCallback; +import com.mogo.och.bus.passenger.callback.IBusPassengerRouteLineInfoCallback; +import com.mogo.och.bus.passenger.model.BusPassengerModel; +import com.mogo.och.bus.passenger.ui.BusPassengerRouteFragment; + +import java.util.List; + +/** + * Created on 2022/3/31 + */ +public class BaseBusPassengerPresenter extends Presenter implements + IBusPassengerADASStatusCallback, IBusPassengerControllerStatusCallback, IBusPassegerDriverStatusCallback, IBusPassengerRouteLineInfoCallback, IBusPassengerAutopilotPlanningCallback { + private static final String TAG = BaseBusPassengerPresenter.class.getSimpleName(); + + public BaseBusPassengerPresenter(BusPassengerRouteFragment view) { + super(view); + BusPassengerModel.getInstance().init(AbsMogoApplication.getApp()); + initListeners(); + } + + @Override + public void onCreate( @NonNull LifecycleOwner owner ) { + super.onCreate( owner ); + CallerLogger.INSTANCE.d( M_BUS_P + TAG, "Bus乘客端Presenter onCreate()" ); + } + + @Override + public void onDestroy( @NonNull LifecycleOwner owner ) { + super.onDestroy( owner ); + + releaseListeners(); + BusPassengerModel.getInstance().release(); + } + + private void initListeners() { + BusPassengerModel.getInstance().setADASStatusCallback(this); + BusPassengerModel.getInstance().setControllerStatusCallback(TAG, this); + BusPassengerModel.getInstance().setDriverStatusCallback(this); + BusPassengerModel.getInstance().setRouteLineInfoCallback(this); + BusPassengerModel.getInstance().setMoGoAutopilotPlanningListener(this); + } + + private void releaseListeners() { + BusPassengerModel.getInstance().setADASStatusCallback(null); + BusPassengerModel.getInstance().setControllerStatusCallback(TAG, null); + BusPassengerModel.getInstance().setDriverStatusCallback(null); + BusPassengerModel.getInstance().setRouteLineInfoCallback(null); + BusPassengerModel.getInstance().setMoGoAutopilotPlanningListener(null); + } + + private void runOnUIThread( Runnable executor ) { + if ( executor == null ) { + return; + } + if ( Looper.myLooper() != Looper.getMainLooper() ) { + UiThreadHandler.post( executor ); + } else { + executor.run(); + } + } + + + @Override + public void onAutopilotArriveEnd() { +// mView.showOverviewFragment(); + } + + @Override + public void onAutopilotEnable() { + runOnUIThread(() -> mView.onAutopilotStatusChanged( + IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE)); + } + + @Override + public void onAutopilotDisable() { + runOnUIThread(() -> mView.onAutopilotStatusChanged( + IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE)); + } + + @Override + public void onAutopilotRunning() { + runOnUIThread(() -> mView.onAutopilotStatusChanged( + IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING)); + } + + @Override + public void onVRModeChanged(boolean isVRMode) { + + } + + @Override + public void onCarLocationChanged(MogoLocation location) { + if (location != null){ + runOnUIThread(() -> mView.onCarLocationChanged(location)); + } + } + + @Override + public void changeOperationStatus(boolean changeStatus) { + runOnUIThread(() -> mView.changeOperationStatus(changeStatus)); + } + + @Override + public void updatePlateNumber(String plateNumber) { + runOnUIThread(() -> mView.updatePlateNum(plateNumber)); + } + + @Override + public void updateLineInfo(String lineName, String lineDurTime) { + runOnUIThread(() -> mView.updateLineInfo(lineName, lineDurTime)); + } + + @Override + public void updateStationsInfo(List stations,int currentStationIndex,boolean isArrived) { + runOnUIThread(() -> mView.updateStationsInfo(stations,currentStationIndex, isArrived)); + } + + @Override + public void showNoTaskView() { + runOnUIThread(() -> mView.showNoTaskView()); + } + + @Override + public void hideNoTaskView() { + runOnUIThread(() -> mView.hideNoTaskView()); + } + + @Override + public void routeResult(List models, int haveArrivedIndex) { + CallerLogger.INSTANCE.d(M_BUS_P + TAG, "routeResult:" + models.size() + + " haveArrivedIndex = "+haveArrivedIndex); + runOnUIThread(() ->mView.routeResult(models,haveArrivedIndex)); + } + + @Override + public void routePlanningToNextStationChanged(long meters, long timeInSecond) { + runOnUIThread(() -> mView.updateRoutePlanningToNextStation(meters, timeInSecond)); + } + + @Override + public void updateTotalDistance() { + runOnUIThread(() -> mView.setProgressBarMax()); + } +} diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerBaseFragment.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerBaseFragment.java new file mode 100644 index 0000000000..fa686d846f --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerBaseFragment.java @@ -0,0 +1,223 @@ +package com.mogo.och.bus.passenger.ui; + +import android.os.Bundle; +import android.text.Html; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.core.widget.ContentLoadingProgressBar; + +import com.mogo.commons.mvp.IView; +import com.mogo.commons.mvp.MvpFragment; + +import com.mogo.commons.mvp.Presenter; +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener; +import com.mogo.eagle.core.function.view.MapBizView; +import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr; +import com.mogo.eagle.core.utilcode.util.UiThreadHandler; +import com.mogo.och.bus.passenger.R; +import com.mogo.och.bus.passenger.constant.BusPassengerConst; +import com.mogo.och.common.module.utils.NumberFormatUtil; + +/** + * Created on 2022/3/31 + *

+ * Bus乘客端基础Fragment + */ +public abstract class BusPassengerBaseFragment> extends MvpFragment { + private static final String TAG = BusPassengerBaseFragment.class.getSimpleName(); + + private MapBizView mapBizView; + private TextView mCurrentArriveStation; + private TextView mCurrentArriveStationTitle; + private TextView mCurrentArriveTip; + private ImageView mAutopilotIv; + private FrameLayout flContainer; + private ContentLoadingProgressBar mProgressBar; + + /** + * 改变自动驾驶状态 + * + * @param status 2 - running 1 - enable 2 - disable + */ + private int mPrevAPStatus = -1; + + @Override + protected int getLayoutId() { + return R.layout.bus_p_base_fragment; + } + + @Override + public String getTagName() { + return TAG; + } + + @Override + protected void initViews() { + mapBizView = findViewById(R.id.mapBizView); + mCurrentArriveStation = findViewById(R.id.bus_p_cur_station_name); + mCurrentArriveStationTitle = findViewById(R.id.bus_p_cur_station_title); + mCurrentArriveTip = findViewById(R.id.bus_p_cur_station_tip); + mAutopilotIv = findViewById(R.id.bus_p_autopilot_iv); + + mProgressBar = findViewById(R.id.bus_progress_bar); + + showRouteFragment(); + +// mCurrentArriveStation.setOnLongClickListener(new View.OnLongClickListener() { +// @Override +// public boolean onLongClick(View v) { +// showOverviewFragment(); +// return false; +// } +// }); + } + + @Override + protected void initViews(Bundle savedInstanceState) { + super.initViews(savedInstanceState); + mapBizView.onCreate(savedInstanceState); + } + + @Override + public void onResume() { + super.onResume(); + mapBizView.onResume(); + } + + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + mapBizView.onSaveInstanceState(outState); + } + + @Override + public void onLowMemory() { + super.onLowMemory(); + mapBizView.onLowMemory(); + } + + @Override + public void onPause() { + super.onPause(); + mapBizView.onPause(); + } + + @Override + public void onDestroyView() { + mapBizView.onDestroy(); + super.onDestroyView(); + } + + /** + * 获取站点面板view,在{@link #initViews()}时候添加到container中 + * + * @return 站点面板view + */ + public abstract int getStationPanelViewId(); + + /** + * 显示线路信息 + */ + public void showRouteFragment() { + flContainer = findViewById(R.id.bus_p_route_panel); + LayoutInflater.from(getContext()).inflate(getStationPanelViewId(), flContainer); + } + + public void updateArrivedStation(String station,int currentIndex,boolean isArrived){ + if (null == station){ + mCurrentArriveStation.setText("----"); + mCurrentArriveStationTitle.setText(getResources().getString(R.string.bus_p_cur_station_title_init)); + mCurrentArriveTip.setText(getResources().getString(R.string.bus_p_cur_station_arrived_tip)); + removeProgressBar(); + }else { + mCurrentArriveStation.setText(station); + if (currentIndex == 0){ + mCurrentArriveStationTitle.setText(getResources().getString(R.string.bus_p_cur_station_title_init)); + mCurrentArriveTip.setText(getResources().getString(R.string.bus_p_cur_station_arrived_tip_init)); + removeProgressBar(); + return; + } + if (isArrived){ + mCurrentArriveStationTitle.setText(getResources().getString(R.string.bus_p_cur_station_title)); + mCurrentArriveTip.setText(getResources().getString(R.string.bus_p_cur_station_arrived_tip)); + removeProgressBar(); + }else { + mCurrentArriveStationTitle.setText(getResources().getString(R.string.bus_p_cur_next_station_title)); + mProgressBar.setVisibility(View.VISIBLE); + } + } + + } + + private void removeProgressBar() { + mProgressBar.setProgress(0); + mProgressBar.setMax(0); + mProgressBar.setVisibility(View.GONE); + } + + public void updateRoutePlanningToNextStation(long meters, long timeInSecond){ + //更新进度条 + updateProgressBar(meters); + String dis = "0"; + String disUnit = "公里"; + if (meters > 0){ + if (meters / 1000 < 1){ + disUnit = "米"; + dis = String.valueOf(Math.round(meters)); + }else { + disUnit = "公里"; + dis = NumberFormatUtil.formatLong((double)meters / 1000); + } + } + String strHtml2 = "距离 " + "" + dis + "" + " "+disUnit+"" + + "   剩余 " + "" + (int)Math.ceil((double)timeInSecond/ 60f) + "" + " 分钟"; + mCurrentArriveTip.setText(Html.fromHtml(strHtml2)); + } + + private void updateProgressBar(long meters) { + int haveDriven = new Long(meters).intValue(); + int progressInt = SharedPrefsMgr.getInstance(getContext()) + .getInt(BusPassengerConst.BUS_SP_KEY_ORDER_SUM_DIS,0) - haveDriven; + mProgressBar.setProgress(progressInt); + } + + public void setProgressBarMax(){ + int max = SharedPrefsMgr.getInstance(getContext()) + .getInt(BusPassengerConst.BUS_SP_KEY_ORDER_SUM_DIS,0); + mProgressBar.setMax(max); + } + + public void onAutopilotStatusChanged(int status) { + getActivity().runOnUiThread(() -> { + // 3. 其他过程直接更新 + if (mPrevAPStatus != status){ + AutopilotStatusChanged(status); + } + mPrevAPStatus = status; + }); + } + + public void AutopilotStatusChanged(int status) { + if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING == status) { + mAutopilotIv.setImageResource(R.drawable.bus_p_auto_nor); + } else if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE == status){ + mAutopilotIv.setImageResource(R.drawable.bus_p_un_auto_nor); + } else { + mAutopilotIv.setImageResource(R.drawable.bus_p_un_auto_nor); + } + + } + + public void showOverviewFragment() { + UiThreadHandler.postDelayed(new Runnable() { + @Override + public void run() { + } + },5000L); + } +} diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerMapDirectionView.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerMapDirectionView.java new file mode 100644 index 0000000000..dcc64d082e --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerMapDirectionView.java @@ -0,0 +1,346 @@ +package com.mogo.och.bus.passenger.ui; + +import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS_P; + +import android.content.Context; +import android.os.Bundle; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.widget.RelativeLayout; + +import androidx.annotation.Nullable; + +import com.amap.api.maps.AMap; +import com.amap.api.maps.CameraUpdate; +import com.amap.api.maps.CameraUpdateFactory; +import com.amap.api.maps.TextureMapView; +import com.amap.api.maps.UiSettings; +import com.amap.api.maps.model.BitmapDescriptor; +import com.amap.api.maps.model.BitmapDescriptorFactory; +import com.amap.api.maps.model.CameraPosition; +import com.amap.api.maps.model.CustomMapStyleOptions; +import com.amap.api.maps.model.LatLng; +import com.amap.api.maps.model.LatLngBounds; +import com.amap.api.maps.model.Marker; +import com.amap.api.maps.model.MarkerOptions; +import com.amap.api.maps.model.Polyline; +import com.amap.api.maps.model.PolylineOptions; +import com.mogo.eagle.core.data.map.MogoLocation; +import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener; +import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.och.bus.passenger.R; +import com.mogo.och.bus.passenger.callback.IBusPassengerMapViewCallback; +import com.mogo.och.bus.passenger.utils.BusPassengerMapAssetStyleUtil; + +import java.util.ArrayList; +import java.util.List; + +/** + * 乘客屏小地图 + */ +public class BusPassengerMapDirectionView + extends RelativeLayout + implements IMoGoChassisLocationGCJ02Listener, + IBusPassengerMapDirectionView, + AMap.OnCameraChangeListener { + + //小地图名称 + public static final String TAG = "TPMapDirectionView"; + + private TextureMapView mAMapNaviView; + private AMap mAMap; + private Marker mCarMarker; + + private List mCoordinatesLatLng = new ArrayList<>(); //轨迹坐标数据 + private List mLineStationLatLng = new ArrayList<>();//站点坐标数据 + private Polyline mPolyline; + private CameraUpdate mCameraUpdate; + private Context mContext; + + List textureList = new ArrayList<>(); + List texIndexList = new ArrayList<>(); + private int mHaveArrivedIndex = 0; + + private List mLineMarkers = new ArrayList<>(); + + private IBusPassengerMapViewCallback mIBusPassengerMapViewCallback; + private BitmapDescriptor mArrivedRes; + private BitmapDescriptor mUnArrivedRes; + + public BusPassengerMapDirectionView(Context context) { + this(context, null); + } + + public BusPassengerMapDirectionView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public BusPassengerMapDirectionView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + try { + initView(context); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void setTaxiPassengerMapViewCallback(IBusPassengerMapViewCallback iBusPassengerMapViewCallback) { + this.mIBusPassengerMapViewCallback = iBusPassengerMapViewCallback; + } + + private void initView(Context context) { + CallerLogger.INSTANCE.d(M_BUS_P + TAG, "initView"); + + mContext = context; + + View smpView = LayoutInflater.from(context).inflate(R.layout.bus_p_map_view, this); + + mAMapNaviView = (TextureMapView) smpView.findViewById(R.id.bus_p_line_amap_view); + + initAMapView(); + + // 注册定位监听 + CallerChassisLocationGCJ02ListenerManager.INSTANCE.addListener(TAG, this); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + // 注册定位监听 + CallerChassisLocationGCJ02ListenerManager.INSTANCE.removeListener(TAG); + } + + private void initAMapView() { +// mCameraUpdate = CameraUpdateFactory.zoomTo(zoomLevel); + mAMap = mAMapNaviView.getMap(); + // 设置导航地图模式,aMap是地图控制器对象。 + mAMap.setMapType(AMap.MAP_TYPE_NIGHT); + + // 关闭显示实时路况图层,aMap是地图控制器对象。 + mAMap.setTrafficEnabled(false); + + // 设置 锚点 图标 + mCarMarker = mAMap.addMarker(new MarkerOptions() + .icon(BitmapDescriptorFactory.fromResource(R.drawable.bus_p_map_car)) + .anchor(0.5f, 0.5f)); + + mArrivedRes = BitmapDescriptorFactory.fromResource(R.drawable.bus_p_map_arrow_arrived); + mUnArrivedRes = BitmapDescriptorFactory.fromResource(R.drawable.bus_p_map_arrow_un_arrive); + + // 加载自定义样式 + CustomMapStyleOptions customMapStyleOptions = new CustomMapStyleOptions() + .setEnable(true) + .setStyleData(BusPassengerMapAssetStyleUtil.getAssetsStyle(getContext(), "map_style.data")) + .setStyleExtraData(BusPassengerMapAssetStyleUtil.getAssetsExtraStyle(getContext(), "map_style_extra.data")); + // 设置自定义样式 + mAMap.setCustomMapStyle(customMapStyleOptions); + + //设置希望展示的地图缩放级别 +// mAMap.moveCamera(mCameraUpdate); + + // 设置地图的样式 + UiSettings uiSettings = mAMap.getUiSettings(); + uiSettings.setZoomControlsEnabled(false);// 地图缩放级别的交换按钮 + uiSettings.setAllGesturesEnabled(false);// 所有手势 + uiSettings.setMyLocationButtonEnabled(false); // 显示默认的定位按钮 + uiSettings.setLogoBottomMargin(-150); //设置Logo下边界距离屏幕底部的边距,设置为负值即可 + + mAMap.setOnMapLoadedListener(new AMap.OnMapLoadedListener() { + @Override + public void onMapLoaded() { + CallerLogger.INSTANCE.d(M_BUS_P + TAG, "smp---onMapLoaded"); + // 加载自定义样式 + CustomMapStyleOptions customMapStyleOptions = new CustomMapStyleOptions() + .setEnable(true) + .setStyleData(BusPassengerMapAssetStyleUtil.getAssetsStyle(getContext(), "map_style.data")) + .setStyleExtraData(BusPassengerMapAssetStyleUtil.getAssetsExtraStyle(getContext(), "map_style_extra.data")); + // 设置自定义样式 + mAMap.setCustomMapStyle(customMapStyleOptions); + mAMapNaviView.getMap().setPointToCenter(mAMapNaviView.getWidth() / 2, mAMapNaviView.getHeight() / 2); + } + }); + + //设置地图状态的监听接口 + mAMap.setOnCameraChangeListener(this); + } + + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + return true; + } + + @Override + public void onChassisLocationGCJ02(@Nullable MogoLocation gnssInfo) { + if (gnssInfo == null) { + return; + } +// CallerLogger.INSTANCE.d(M_BUS_P + TAG, "onCarLocationChanged2 :" + location.getLatitude() + ":" + location.getLongitude()); + LatLng currentLatLng = new LatLng(gnssInfo.getLatitude(), gnssInfo.getLongitude()); + + //更新车辆位置 + if (mCarMarker != null) { +// CallerLogger.INSTANCE.d(M_BUS_P + TAG, "location.getBearing() = " + location.getBearing()); + mCarMarker.setRotateAngle((float) (360 - gnssInfo.getHeading())); + mCarMarker.setPosition(currentLatLng); + mCarMarker.setToTop(); + } + + //圈定地图显示范围 + LatLngBounds.Builder boundsBuilder = new LatLngBounds.Builder(); + + if (mCoordinatesLatLng.size() > 0){ + //存放经纬度 + for (int i = 0; i < mCoordinatesLatLng.size(); i++) { + boundsBuilder.include(mCoordinatesLatLng.get(i)); + } + //第二个参数为四周留空宽度 + }else if (mLineStationLatLng.size() > 0){ + for (int i = 0; i< mLineStationLatLng.size();i++){ + boundsBuilder.include(mLineStationLatLng.get(i)); + } + } + + boundsBuilder.include(currentLatLng); + mAMap.moveCamera(CameraUpdateFactory.newLatLngBoundsRect(boundsBuilder.build(),100,100,100,100)); + } + + + @Override + public void drawablePolyline() { + if (mPolyline != null) { + mPolyline.remove(); + } + if (mAMap != null) { + + addRouteColorList(); + CallerLogger.INSTANCE.d(M_BUS_P + TAG, "mLinePointsLatLng.size() = " +mLineStationLatLng.size() + +" mCoordinatesLatLng.size()= " + mCoordinatesLatLng.size()); + if (mLineStationLatLng.size() >= 2 && mCoordinatesLatLng.size() > 2) { + //设置线段纹理 + PolylineOptions polylineOptions = new PolylineOptions(); + polylineOptions.addAll(mCoordinatesLatLng); + polylineOptions.width(14); //线段宽度 + polylineOptions.setUseTexture(true); + polylineOptions.lineCapType(PolylineOptions.LineCapType.LineCapRound); + polylineOptions.setCustomTextureList(textureList); + polylineOptions.setCustomTextureIndex(texIndexList); +// polylineOptions.colorValues(colorList); +// polylineOptions.setCustomTexture(BitmapDescriptorFactory.fromResource(R.drawable.taxi_p_map_arrow)); + + // 绘制线 + mPolyline = mAMap.addPolyline(polylineOptions); + + } + } + } + + /** + * 添加画线颜色值 + */ + private void addRouteColorList() { + textureList.clear(); + texIndexList.clear(); + for (int i = 0; i < mCoordinatesLatLng.size(); i++){ + if (i <= mHaveArrivedIndex){ + textureList.add(mArrivedRes); + }else { + textureList.add(mUnArrivedRes); + } + texIndexList.add(i); + } + } + + @Override + public void clearPolyline() { + if (mPolyline != null) { + mPolyline.remove(); + } + } + + @Override + public void setLineMarker() { + + } + + public void clearCoordinatesLatLng(){ + textureList.clear(); + texIndexList.clear(); + mCoordinatesLatLng.clear(); + mLineStationLatLng.clear(); + CallerLogger.INSTANCE.d(M_BUS_P + TAG, " mCoordinatesLatLng.clear " ); + } + + public void onCreateView(Bundle savedInstanceState) { + if (mAMapNaviView != null) { + mAMapNaviView.onCreate(savedInstanceState); + } + } + + public void onResume() { + if (mAMapNaviView != null) { + mAMapNaviView.onResume(); + } + } + + public void onPause() { + if (mAMapNaviView != null) { + mAMapNaviView.onPause(); + } + } + + public void onDestroy() { + if (mAMapNaviView != null) { + mAMapNaviView.onDestroy(); + } + } + + public void setCoordinatesLatLng(List latLngs,int haveArrivedIndex) { + mCoordinatesLatLng.clear(); + mCoordinatesLatLng.addAll(latLngs); + mHaveArrivedIndex = haveArrivedIndex; + } + + public void clearLineMarkers(){ + for (int i =0; i< mLineMarkers.size();i++){ + mLineMarkers.get(i).setVisible(false); + mLineMarkers.get(i).remove(); + } + mLineMarkers.clear(); + } + + public void setLinePointMarkerAndDraw(List mLineStationsList, int currentIndex) { + clearLineMarkers(); + mLineStationLatLng.clear(); + mLineStationLatLng.addAll(mLineStationsList); + + if (mLineStationsList.size() > 0){ + for (int i = 0; i < mLineStationsList.size(); i++) { + if (currentIndex == i){ + Marker mEndMarker = mAMap.addMarker(new MarkerOptions() + .icon(BitmapDescriptorFactory.fromResource(R.drawable.bus_p_map_view_dir_end_point))); + mEndMarker.setPosition(mLineStationsList.get(i)); + mLineMarkers.add(i,mEndMarker); + }else { + Marker mStartMarker = mAMap.addMarker(new MarkerOptions() + .icon(BitmapDescriptorFactory.fromResource(R.drawable.bus_p_map_view_dir_way_point))); + mStartMarker.setPosition(mLineStationsList.get(i)); + mLineMarkers.add(i,mStartMarker); + } + } + } + } + + @Override + public void onCameraChange(CameraPosition cameraPosition) { + mIBusPassengerMapViewCallback.onCameraChange(cameraPosition.bearing); + } + + @Override + public void onCameraChangeFinish(CameraPosition cameraPosition) { + + } +} diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerRouteFragment.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerRouteFragment.java new file mode 100644 index 0000000000..9d7393f968 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerRouteFragment.java @@ -0,0 +1,314 @@ +package com.mogo.och.bus.passenger.ui; + +import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS_P; + +import android.os.Bundle; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.RotateAnimation; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.constraintlayout.widget.ConstraintLayout; +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.data.map.MogoLocation; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.eagle.core.utilcode.mogo.storage.SharedPrefsMgr; +import com.mogo.och.bus.passenger.R; +import com.mogo.och.bus.passenger.adapter.BusPassengerLineStationsAdapter; +import com.mogo.och.bus.passenger.bean.BusPassengerStation; +import com.mogo.och.bus.passenger.callback.IBusPassengerMapViewCallback; +import com.mogo.och.bus.passenger.constant.BusPassengerConst; +import com.mogo.och.bus.passenger.presenter.BaseBusPassengerPresenter; +import com.mogo.och.bus.passenger.ui.layoutmanager.CenterLayoutManager; +import com.mogo.och.bus.passenger.utils.BPRouteDataTestUtils; +import com.mogo.och.common.module.wigets.MarqueeTextView; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author: wangmingjun + * @date: 2022/4/12 + */ +public class BusPassengerRouteFragment extends + BusPassengerBaseFragment + implements IBusPassengerMapViewCallback { + + private final String TAG = "BusPassengerRouteFragment"; + + private final List mStationsList = new ArrayList<>(); + + private TextView mSpeedTv; + private ConstraintLayout mNoLineInfoView; + private TextView mCarPlateNum; + private MarqueeTextView mLineName; + private TextView mOperationTime; + private ConstraintLayout mRouteInfoView; + private RecyclerView mStationsListRv; + private BusPassengerMapDirectionView mMapDirectionView; + private ImageView mMapArrowIcon; + private RotateAnimation rotateAnimation; + private float lastBearing = 0; + private BusPassengerLineStationsAdapter mAdapter; + private TextView emptyTv; + + @Override + public int getStationPanelViewId() { + return R.layout.bus_p_route_fragment; + } + + @NonNull + @Override + protected BaseBusPassengerPresenter createPresenter() { + return new BaseBusPassengerPresenter(this); + } + + @Override + protected void initViews() { + super.initViews(); + + mSpeedTv = findViewById(R.id.bus_p_speed_tv); + + mNoLineInfoView =findViewById(R.id.bus_p_no_order_data_view); + emptyTv = findViewById(R.id.no_order_data_tv); + + mCarPlateNum = findViewById(R.id.bus_p_driver_num_plate_tv); + mLineName = findViewById(R.id.bus_p_line_name_tv); + mOperationTime = findViewById(R.id.line_operation_time_tv); + + mRouteInfoView = findViewById(R.id.bus_p_line_cl); + mStationsListRv = findViewById(R.id.bus_p_line_stations_rl); + + CenterLayoutManager manager = new CenterLayoutManager(getContext()); + mStationsListRv.setLayoutManager(manager); + mAdapter = new BusPassengerLineStationsAdapter(getContext(), mStationsList); + mStationsListRv.setAdapter(mAdapter); + + mMapArrowIcon = findViewById(R.id.bus_p_arrow_nor); + + //测试 + if (DebugConfig.isDebug()){ + mSpeedTv.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + BPRouteDataTestUtils.converToRouteData(); + return false; + } + }); + } + } + + @Override + protected void initViews(Bundle savedInstanceState) { + super.initViews(savedInstanceState); + mMapDirectionView = findViewById(R.id.bus_p_line_map_view); + mMapDirectionView.onCreateView(savedInstanceState); + mMapDirectionView.setTaxiPassengerMapViewCallback(this); + } + + @Override + public void onResume() { + super.onResume(); + if (mMapDirectionView != null) { + mMapDirectionView.onResume(); + } + } + + @Override + public void onPause() { + super.onPause(); + if (mMapDirectionView != null) { + mMapDirectionView.onPause(); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (mMapDirectionView != null) { + mMapDirectionView.onDestroy(); + } + } + + public void routeResult(List latLngList,int haveArrivedIndex) { + if (latLngList.size() > 0) { + drawablePolyline(latLngList,haveArrivedIndex); + } else { + clearMapView(); + } + } + + /** + * 绘制 + * + * @param coordinates + */ + private void drawablePolyline(List coordinates,int haveArrivedIndex) { + if (mMapDirectionView != null) { + mMapDirectionView.setCoordinatesLatLng(coordinates,haveArrivedIndex); + UiThreadHandler.post(new Runnable() { + @Override + public void run() { + mMapDirectionView.drawablePolyline(); + } + }); + } + } + + public void clearMapView() { + if (mMapDirectionView != null) { + UiThreadHandler.post(new Runnable() { + @Override + public void run() { + mMapDirectionView.clearPolyline(); + mMapDirectionView.clearCoordinatesLatLng(); + } + }); + } + } + + public void clearMapMarkers() { + if (mMapDirectionView != null) { + UiThreadHandler.post(new Runnable() { + @Override + public void run() { + mMapDirectionView.clearLineMarkers(); + + } + }); + } + } + + public void changeOperationStatus(boolean status) { + if (status) { + mNoLineInfoView.setVisibility(View.GONE); + mRouteInfoView.setVisibility(View.VISIBLE); + } else { + emptyTv.setText(getString(R.string.bus_p_no_out)); + mNoLineInfoView.setVisibility(View.VISIBLE); + mRouteInfoView.setVisibility(View.GONE); + updateArrivedStation(null,0,true); + clearMapView(); + clearMapMarkers(); + } + } + + public void showNoTaskView(){ + if (mNoLineInfoView.getVisibility() == View.GONE){ + mNoLineInfoView.setVisibility(View.VISIBLE); + mRouteInfoView.setVisibility(View.GONE); + updateArrivedStation(null,0,true); + clearMapView(); + clearMapMarkers(); + } + emptyTv.setText(getString(R.string.bus_p_no_task)); + } + + public void hideNoTaskView(){ + if (mNoLineInfoView.getVisibility() == View.VISIBLE){ + mNoLineInfoView.setVisibility(View.GONE); + mRouteInfoView.setVisibility(View.VISIBLE); + } + } + + public void updatePlateNum(String plateNum){ + if ("".equals(plateNum) || null == plateNum) { + mCarPlateNum.setText("-- --"); + }else { + mCarPlateNum.setText((plateNum)); + } + } + + public void updateLineInfo(String lineName, String lineDurTime) { + mLineName.setText(lineName); + mOperationTime.setText(lineDurTime); + } + + /** + * + * @param stations + * @param currentStationIndex + * @param isArrived 是否到站并离开,true 到达当前站 currentStationIndex 未离开, false 正在前往此站 currentStationIndex + */ + public void updateStationsInfo(List stations, int currentStationIndex,boolean isArrived) { + updateArrivedStation(stations.get(currentStationIndex).getName(),currentStationIndex,isArrived); + mStationsList.clear(); + mStationsList.addAll(stations); + mAdapter.notifyDataSetChanged(); + + if (currentStationIndex > -1){ + updateCurrentStation(currentStationIndex); + } + + if (currentStationIndex == 0 && isArrived){ //到达始发站且并未出发, 恢复站点marker 清楚路径 清空路径点 + SharedPrefsMgr.getInstance(getContext()) + .remove(BusPassengerConst.BUS_SP_KEY_ORDER_SUM_DIS); + clearMapView(); + } + + if (stations.size() > 0){ + updateWayPointList(stations,currentStationIndex); + } + } + + private void updateWayPointList(List stations,int currentStationIndex) { + List mLineStationsList = new ArrayList<>(); + for (int i = 0; i< stations.size(); i++) {//站点集合 +// LatLng latLng = CoordinateCalculateRouteUtil.coordinateConverterWgsToGcj(getContext() +// ,stations.get(i).getLon(),stations.get(i).getLat());// lat,lon + LatLng latLng = new LatLng(stations.get(i).getGcjLat(),stations.get(i).getGcjLon());// lat,lon + mLineStationsList.add(latLng); + } + + if (mMapDirectionView != null) { + UiThreadHandler.post(new Runnable() { + @Override + public void run() { + mMapDirectionView.setLinePointMarkerAndDraw(mLineStationsList,currentStationIndex); + } + }); + } + } + + @Override + public void onCameraChange(float bearing) { + startIvCompass(bearing); + } + + /** + * 设置指南针旋转 + * + * @param bearing + */ + private void startIvCompass(float bearing) { + bearing = 360 - bearing; + CallerLogger.INSTANCE.d(M_BUS_P + TAG, "startIvCompass: " + bearing); + rotateAnimation = new RotateAnimation(lastBearing, bearing, Animation.RELATIVE_TO_SELF + , 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); + rotateAnimation.setFillAfter(true); + + mMapArrowIcon.startAnimation(rotateAnimation); + lastBearing = bearing; + } + + public void onCarLocationChanged(MogoLocation location) { + updateSpeedView((float) location.getGnssSpeed()); + } + + public void updateSpeedView(float speed){ + int speedKM = (int) (Math.abs(speed) * 3.6F); + mSpeedTv.setText(String.valueOf(speedKM)); + } + + public void updateCurrentStation(int position) { + if (mStationsListRv != null){ + mStationsListRv.smoothScrollToPosition(position); + } + } +} diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerTrafficLightView.kt b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerTrafficLightView.kt new file mode 100644 index 0000000000..67fbc4b554 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/BusPassengerTrafficLightView.kt @@ -0,0 +1,179 @@ +package com.mogo.och.bus.passenger.ui + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import com.mogo.eagle.core.data.enums.DataSourceType +import com.mogo.eagle.core.data.enums.TrafficLightEnum +import com.mogo.eagle.core.function.api.datacenter.union.IMoGoTrafficLightListener +import com.mogo.eagle.core.function.call.v2x.CallerTrafficLightListenerManager +import com.mogo.eagle.core.utilcode.util.UiThreadHandler +import com.mogo.och.bus.passenger.R +import kotlinx.android.synthetic.jinlvvan.bus_p_traffic_light_view.view.* + +/** + * bus乘客端:红绿灯view + * + * Created on 2022/3/14 + */ +class BusPassengerTrafficLightView @JvmOverloads constructor( + context: Context?, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : LinearLayout(context, attrs, defStyleAttr), IMoGoTrafficLightListener { + + companion object { + private const val TAG = "BusPassengerTrafficLightView" + } + + private var mCurrentLightId = TrafficLightEnum.BLACK + + init { + init(context) + } + + private fun init(context: Context?) { + LayoutInflater.from(context).inflate(R.layout.bus_p_traffic_light_view, this, true) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + CallerTrafficLightListenerManager.addListener(TAG, this) + } + + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + CallerTrafficLightListenerManager.removeListener(TAG) + } + + /** + * 展示红绿灯预警 + * + * @param checkLightId 0-都是默认,1-红,2-黄,3-绿 + * @param lightSource 1:云端下发;2:自车感知 + */ + override fun showTrafficLight(checkLightId: TrafficLightEnum, lightSource: DataSourceType) { + super.showTrafficLight(checkLightId, lightSource) + mCurrentLightId = checkLightId + updateTrafficLightIcon(checkLightId) + } + + /** + * 关闭红绿灯预警展示,并重制灯态 + */ + override fun disableTrafficLight() { + super.disableTrafficLight() + UiThreadHandler.post { + mCurrentLightId = TrafficLightEnum.BLACK + this@BusPassengerTrafficLightView.visibility = GONE + } + } + + /** + * @param redNum 红灯倒计时 + * @param yellowNum 黄灯倒计时 + * @param greenNum 绿灯倒计时 + */ + override fun changeCountdownTrafficLightNum(redNum: Int, yellowNum: Int, greenNum: Int) { + super.changeCountdownTrafficLightNum(redNum, yellowNum, greenNum) + resetView() + when (mCurrentLightId) { + TrafficLightEnum.RED -> changeCountdownRed(redNum) + TrafficLightEnum.YELLOW -> changeCountdownYellow(yellowNum) + TrafficLightEnum.GREEN -> changeCountdownGreen(greenNum) + else -> UiThreadHandler.post { bus_p_traffic_light_time_tv.text = "" } + } + } + + override fun changeCountdownRed(redNum: Int) { + super.changeCountdownRed(redNum) + UiThreadHandler.post { + if (redNum > 0) { + resetView() + bus_p_traffic_light_time_tv.text = redNum.toString() + } else { + disableTrafficLightCountDown() + bus_p_traffic_light_time_tv.text = "" + } + } + } + + override fun changeCountdownGreen(greenNum: Int) { + super.changeCountdownGreen(greenNum) + UiThreadHandler.post { + if (greenNum > 0) { + resetView() + bus_p_traffic_light_time_tv.text = greenNum.toString() + } else { + disableTrafficLightCountDown() + bus_p_traffic_light_time_tv.text = "" + } + } + } + + override fun changeCountdownYellow(yellowNum: Int) { + super.changeCountdownYellow(yellowNum) + UiThreadHandler.post { + if (yellowNum > 0) { + resetView() + bus_p_traffic_light_time_tv.text = yellowNum.toString() + } else { + disableTrafficLightCountDown() + bus_p_traffic_light_time_tv.text = "" + } + } + } + + /** + * 更新红绿灯icon + * + * @param lightId 0-都是默认,1-红,2-黄,3-绿 + */ + private fun updateTrafficLightIcon(lightId: TrafficLightEnum) { + UiThreadHandler.post { + when (lightId) { + TrafficLightEnum.RED -> { + bus_p_traffic_light_iv.setBackgroundResource(R.drawable.bus_p_light_red_nor) + this@BusPassengerTrafficLightView.visibility = VISIBLE + } + TrafficLightEnum.YELLOW -> { + bus_p_traffic_light_iv.setBackgroundResource(R.drawable.bus_p_light_yellow_nor) + this@BusPassengerTrafficLightView.visibility = VISIBLE + } + TrafficLightEnum.GREEN -> { + bus_p_traffic_light_iv.setBackgroundResource(R.drawable.bus_p_light_green_nor) + this@BusPassengerTrafficLightView.visibility = VISIBLE + } + else -> this@BusPassengerTrafficLightView.visibility = GONE + } + } + } + + override fun disableTrafficLightCountDown() { + super.disableTrafficLightCountDown() + UiThreadHandler.post { + val layoutParams = layoutParams + if (layoutParams is MarginLayoutParams) { + val lp = layoutParams + lp.width = resources.getDimension(R.dimen.bus_p_traffic_light_icon_size).toInt() + setLayoutParams(lp) + bus_p_traffic_light_time_tv.visibility = GONE + bus_p_traffic_light_bg.layoutParams.width = + resources.getDimension(R.dimen.dp_90).toInt() + } + } + } + + private fun resetView() { + val layoutParams = layoutParams + if (layoutParams is MarginLayoutParams) { + val lp = layoutParams + lp.width = resources.getDimension(R.dimen.bus_p_route_traffic_light_view_width).toInt() + setLayoutParams(lp) + bus_p_traffic_light_time_tv.visibility = VISIBLE + bus_p_traffic_light_bg.layoutParams.width = + resources.getDimension(R.dimen.bus_p_traffic_light_bg_width).toInt() + } + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/IBusPassengerMapDirectionView.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/IBusPassengerMapDirectionView.java new file mode 100644 index 0000000000..7f525d0464 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/IBusPassengerMapDirectionView.java @@ -0,0 +1,23 @@ +package com.mogo.och.bus.passenger.ui; + +/** + * @author xiaoyuzhou + * @date 2021/6/24 11:33 上午 + */ +public interface IBusPassengerMapDirectionView { + + /** + * 绘制路径线 + */ + void drawablePolyline(); + + /** + * 清除路径线 + */ + void clearPolyline(); + + /** + * 设置路径中起终点marker + */ + void setLineMarker(); +} diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/layoutmanager/CenterLayoutManager.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/layoutmanager/CenterLayoutManager.java new file mode 100644 index 0000000000..42210cbcaf --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/ui/layoutmanager/CenterLayoutManager.java @@ -0,0 +1,42 @@ +package com.mogo.och.bus.passenger.ui.layoutmanager; + +import android.content.Context; +import android.util.AttributeSet; + +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.LinearSmoothScroller; +import androidx.recyclerview.widget.RecyclerView; + +public class CenterLayoutManager extends LinearLayoutManager { + public CenterLayoutManager(Context context) { + super(context); + } + + public CenterLayoutManager(Context context, int orientation, boolean reverseLayout) { + super(context, orientation, reverseLayout); + } + + public CenterLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override + public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) { + RecyclerView.SmoothScroller smoothScroller = new CenterSmoothScroller(recyclerView.getContext()); + smoothScroller.setTargetPosition(position); + startSmoothScroll(smoothScroller); + } + + private static class CenterSmoothScroller extends LinearSmoothScroller { + + CenterSmoothScroller(Context context) { + super(context); + } + + @Override + public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int snapPreference) { + return (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2); + } + } + +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/utils/BPRouteDataTestUtils.java b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/utils/BPRouteDataTestUtils.java new file mode 100644 index 0000000000..ac7db3446d --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/java/com/mogo/och/bus/passenger/utils/BPRouteDataTestUtils.java @@ -0,0 +1,58 @@ +package com.mogo.och.bus.passenger.utils; + +import com.mogo.och.bus.passenger.model.BusPassengerModel; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.List; + +import mogo.telematics.pad.MessagePad; + +/** + * @author: wangmingjun + * @date: 2022/4/13 + */ +public class BPRouteDataTestUtils { + + //13号路口起-13号路口终 +// static String jsonStr ="{\n" + +// " \"models\": [\n" + +// " {\n" + +// " \"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19927760268911,\"lon\":116.73512607061035,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19927736555187,\"lon\":116.73498243020299,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19927135941599,\"lon\":116.73482951462647,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199260672670036,\"lon\":116.73468429259535,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199251260349946,\"lon\":116.73453933465,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19924691997577,\"lon\":116.7343756435551,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199247953493625,\"lon\":116.73421240809087,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19924986849947,\"lon\":116.73400425509712,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199249431152175,\"lon\":116.73378579041055,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199248921305724,\"lon\":116.73357811807278,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19925012387371,\"lon\":116.73337650020184,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199252270195075,\"lon\":116.73318223781153,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.1992521615169,\"lon\":116.73298632625203,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19925202633083,\"lon\":116.73279582043983,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199261230205735,\"lon\":116.73263403473568,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199327991681926,\"lon\":116.73251962434813,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19944850496711,\"lon\":116.73249661840195,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199582026896415,\"lon\":116.73251038561487,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199743326352014,\"lon\":116.73253087453938,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199908347167394,\"lon\":116.73255070500186,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200065950595445,\"lon\":116.7325720694418,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20022747460407,\"lon\":116.73259461416663,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200384057310536,\"lon\":116.73261575018056,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20053849777916,\"lon\":116.73263451936387,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200696919444624,\"lon\":116.7326540541723,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2008524952796,\"lon\":116.7326743511824,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20101429705625,\"lon\":116.73269393580199,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20118279997041,\"lon\":116.73271564378308,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201342388452076,\"lon\":116.73273653366076,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201476063822355,\"lon\":116.73275292393079,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20163479199852,\"lon\":116.73277440686762,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20181243476041,\"lon\":116.7328052766508,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201991767093304,\"lon\":116.7328453845644,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20215573733484,\"lon\":116.73287624009339,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202313648759784,\"lon\":116.73289887933315,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202434745374454,\"lon\":116.7329182210956,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20253164952098,\"lon\":116.73297539811277,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20258043275509,\"lon\":116.73312335324984,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20258233576585,\"lon\":116.73331077089557,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20257107560234,\"lon\":116.73351244039137,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202561578580514,\"lon\":116.73370176209845,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20256256788661,\"lon\":116.73391325024126,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20255633158834,\"lon\":116.73413195000244,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202543311179575,\"lon\":116.73436614303907,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20253067346457,\"lon\":116.73458032609663,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20251776111356,\"lon\":116.73477082198242,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202503997557805,\"lon\":116.73498624001282,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20249129260376,\"lon\":116.73518976336872,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247877796589,\"lon\":116.73537786253135,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20246651610268,\"lon\":116.73559239130266,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20245754388014,\"lon\":116.73574239922202,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20244749208,\"lon\":116.73589674090469,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243806550113,\"lon\":116.73607057284322,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243550556816,\"lon\":116.73628106525871,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243654127756,\"lon\":116.7364949950665,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243738221016,\"lon\":116.7367061649993,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243672476754,\"lon\":116.73691115930336,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243590788176,\"lon\":116.73710722104272,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202436434375336,\"lon\":116.73730688607075,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243749821501,\"lon\":116.73750140347998,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243625962803,\"lon\":116.73771330926793,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202434515480725,\"lon\":116.73791895606205,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2024326561388,\"lon\":116.73815206945737,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243092086137,\"lon\":116.73838655528765,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202430876006126,\"lon\":116.73861890759498,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20242914053177,\"lon\":116.73882029918758,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20242843336561,\"lon\":116.73904465495175,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20242661219026,\"lon\":116.73922453252953,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202426462811076,\"lon\":116.7393708046956,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20242687134937,\"lon\":116.73954685547025,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20242694967377,\"lon\":116.73975021183773,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202424630601236,\"lon\":116.73999740812975,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202422502184625,\"lon\":116.74028266774337,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202419634158936,\"lon\":116.7405942561498,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241975959762,\"lon\":116.7409069557092,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241920524113,\"lon\":116.74120156191647,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241765540262,\"lon\":116.74149288504978,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241569149764,\"lon\":116.7418080096762,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202414529497084,\"lon\":116.74210262897205,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241419532155,\"lon\":116.74241767661879,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202413879360954,\"lon\":116.7427571218185,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241287045245,\"lon\":116.7431284691325,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241214965105,\"lon\":116.74343354359334,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241141271715,\"lon\":116.7437220210538,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2024080520075,\"lon\":116.74399113498052,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202391714280026,\"lon\":116.74427625698272,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20238163805639,\"lon\":116.74452083315958,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202379293010274,\"lon\":116.74475703837204,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202379007817086,\"lon\":116.7449961645494,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20237814181231,\"lon\":116.7452036063558,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202375477619896,\"lon\":116.74539567654291,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2023632396621,\"lon\":116.74555457589031,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20229396554444,\"lon\":116.7456716047369,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20217800547467,\"lon\":116.74574081942625,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202047498095304,\"lon\":116.74573659255675,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20188573786706,\"lon\":116.74571018281719,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201738240263026,\"lon\":116.74568463148606,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20157507049073,\"lon\":116.74565525041498,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20137985142042,\"lon\":116.745619970576,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201187335613575,\"lon\":116.74558631350607,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20098251429043,\"lon\":116.74555055587679,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2007748533628,\"lon\":116.74551426934663,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20057082986032,\"lon\":116.74547749663195,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20036944224329,\"lon\":116.74544156175533,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20016365229035,\"lon\":116.74540577510051,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.1999958572445,\"lon\":116.74537505807076,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19984100521566,\"lon\":116.7453433678602,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.1996863960282,\"lon\":116.74529675648621,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19953919567943,\"lon\":116.74525916493474,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19940587189373,\"lon\":116.74523402869453,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19929047792381,\"lon\":116.74518617038383,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922141745155,\"lon\":116.74506912884067,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19920798885308,\"lon\":116.744896716334,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19920912644279,\"lon\":116.74467216715483,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199209186509314,\"lon\":116.74448257515108,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19920910709997,\"lon\":116.74430613406223,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.1992100786082,\"lon\":116.74410888316238,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19921081961254,\"lon\":116.74391968819582,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19921040855518,\"lon\":116.7437082083402,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19921085053439,\"lon\":116.74346931155634,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19921197237373,\"lon\":116.74325149697013,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19921248248983,\"lon\":116.74301103786591,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.1992139724646,\"lon\":116.74277237066539,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199215818352386,\"lon\":116.74253219408898,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199216175018876,\"lon\":116.74228853120842,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199215970354246,\"lon\":116.74204663206451,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199216627492966,\"lon\":116.74183871233049,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19921789170398,\"lon\":116.74165788334192,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922000138535,\"lon\":116.74144512197054,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199221559127494,\"lon\":116.741249370491,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922287231889,\"lon\":116.7410525810756,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922229019589,\"lon\":116.74085266662037,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.1992216995901,\"lon\":116.74061957723823,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922263073874,\"lon\":116.74041638149129,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922478093337,\"lon\":116.7402123910757,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199227066091595,\"lon\":116.74003419421553,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199228634241756,\"lon\":116.73985841944678,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922951636012,\"lon\":116.7397079274105,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199252095329484,\"lon\":116.73956265582487,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199346162997905,\"lon\":116.73944690416265,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199470799628024,\"lon\":116.73941941053417,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19962513314346,\"lon\":116.7394280706812,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199780626058924,\"lon\":116.73944255215424,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199961525343376,\"lon\":116.73945856750177,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20016196947193,\"lon\":116.73947572081121,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200384479551936,\"lon\":116.7394949225795,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200595083817475,\"lon\":116.73951027963179,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200792203321086,\"lon\":116.73952526850614,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200985930701684,\"lon\":116.73954125209579,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20115978977055,\"lon\":116.73955610094161,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201321019536124,\"lon\":116.7395695239138,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20147117943043,\"lon\":116.7395823299481,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20163699848565,\"lon\":116.73959633422596,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20178484338371,\"lon\":116.7396085776486,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201962185646316,\"lon\":116.73962351991214,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2021018923927,\"lon\":116.7396354059821,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2022137620686,\"lon\":116.73964348380458,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20232600820075,\"lon\":116.73961190446633,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241090270993,\"lon\":116.73951649703137,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20245777783807,\"lon\":116.73937664238166,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20246906634823,\"lon\":116.73920146119093,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202470916682884,\"lon\":116.73898763065634,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247034830421,\"lon\":116.73878158418357,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20246978204673,\"lon\":116.73857680142473,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247082638905,\"lon\":116.73834517890637,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202471943178196,\"lon\":116.7381047689514,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247131648035,\"lon\":116.73787761484981,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202470799473765,\"lon\":116.73766230702478,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247013054322,\"lon\":116.73743619407796,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20246999515433,\"lon\":116.73724916823292,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247199652478,\"lon\":116.73704888970806,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202473960263525,\"lon\":116.73684083235807,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202474504753205,\"lon\":116.73665462440796,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247501354581,\"lon\":116.73650710371837,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20246541231906,\"lon\":116.73635807696789,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202426768984274,\"lon\":116.73622283382787,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20236638788854,\"lon\":116.73610589402243,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20227106919894,\"lon\":116.73600895001849,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2021428343084,\"lon\":116.73596816020945,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20197815580698,\"lon\":116.73594623645097,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20181789535303,\"lon\":116.73593148707488,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201667906886954,\"lon\":116.73591743008926,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201505897730755,\"lon\":116.7359002912543,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20135083580946,\"lon\":116.73588579696379,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20118617904595,\"lon\":116.73586970398149,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20102374028594,\"lon\":116.73585314703226,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20085554043743,\"lon\":116.73583763953049,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20069451888229,\"lon\":116.73582073901778,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200530837344964,\"lon\":116.73580314359012,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2003608457064,\"lon\":116.73578183888779,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20021770046798,\"lon\":116.73575292592922,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20003454701824,\"lon\":116.7357174959358,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19986125116602,\"lon\":116.73569499961796,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19969408518737,\"lon\":116.73567725223492,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19955533048882,\"lon\":116.73566375985422,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19943174810538,\"lon\":116.73564927714162,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19933167546824,\"lon\":116.735595995086,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199280357603875,\"lon\":116.73546293260645,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19927848361656,\"lon\":116.73531579486274,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19928127892504,\"lon\":116.73505848474375,\"speed\": 0.0\n" + +// " }\n" + +// " ]\n" + +// "}"; + + //洱海轨迹 + static String jsonStr ="{\n" + + " \"models\": [\n" + + " {\n" + + "\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87506159122434,\"longitude_\":100.13463113454593,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874963432017065,\"longitude_\":100.13431083742782,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87481475105022,\"longitude_\":100.13402921175965,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874646001578594,\"longitude_\":100.13381071517328,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874280379177108,\"longitude_\":100.13344505101841,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87422474353087,\"longitude_\":100.13336522063217,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.8741846037573,\"longitude_\":100.13326081770579,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874169301193604,\"longitude_\":100.133157732712,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87417865388365,\"longitude_\":100.13305383003687,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87424355168725,\"longitude_\":100.13288988207758,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87441186213399,\"longitude_\":100.1326293335985,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874490698935094,\"longitude_\":100.13247594955229,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874551609777672,\"longitude_\":100.13227787460397,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874574232444672,\"longitude_\":100.1320943662068,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874574936235152,\"longitude_\":100.13109176087639,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874553271326842,\"longitude_\":100.13095333429315,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874468877309848,\"longitude_\":100.1307193884582,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874449652750723,\"longitude_\":100.1306199898516,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874449487671647,\"longitude_\":100.13046154976821,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87448439242463,\"longitude_\":100.13030173580755,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874554236422213,\"longitude_\":100.13013644761386,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874657614202334,\"longitude_\":100.1299792051648,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874777620037,\"longitude_\":100.12985830283493,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.8749211786138,\"longitude_\":100.12975642056448,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.875123187810807,\"longitude_\":100.12965486650492,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.875282658783302,\"longitude_\":100.12960819854966,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87555277290776,\"longitude_\":100.12954493830546,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.875686392944456,\"longitude_\":100.12948797177033,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87609150201856,\"longitude_\":100.12914349760804,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87645852877848,\"longitude_\":100.1289124421148,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87667085149294,\"longitude_\":100.1288070141346,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.877063427631544,\"longitude_\":100.12866094818,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87751767381502,\"longitude_\":100.1286538378911,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87776644058061,\"longitude_\":100.12861180318971,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87866240134362,\"longitude_\":100.12843614360035,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.879103098247672,\"longitude_\":100.12837521690956,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.879326467139197,\"longitude_\":100.12832846342278,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.8800083487784,\"longitude_\":100.12811951944514,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.88019070137511,\"longitude_\":100.12802255167708,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.880357426115513,\"longitude_\":100.12787083439976,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.880481954487596,\"longitude_\":100.1276940858994,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.880653097994426,\"longitude_\":100.12740127585158,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.880758517533007,\"longitude_\":100.12730743064938,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.880799507331627,\"longitude_\":100.12724835914499,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.88098572681533,\"longitude_\":100.12658255210448,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.881039332211476,\"longitude_\":100.1263847771375,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.881100185621683,\"longitude_\":100.12625820340021,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.881198711287677,\"longitude_\":100.12611952057267,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.88133930457031,\"longitude_\":100.12599337741426,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.881467122690022,\"longitude_\":100.12592180492642,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.88159423650277,\"longitude_\":100.12588048516646,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.882012210316635,\"longitude_\":100.12584119198453,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.88240347787595,\"longitude_\":100.12581569076075,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.882530989675523,\"longitude_\":100.1258417579907,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.88266718412272,\"longitude_\":100.1258996456634,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.882846062879587,\"longitude_\":100.12604302069693,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.883143169798704,\"longitude_\":100.12643363872347,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.883316147374213,\"longitude_\":100.12660436351877,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.883516631635977,\"longitude_\":100.12670006660859,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.884412161186358,\"longitude_\":100.12681096840119,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.88456077756699,\"longitude_\":100.12680626559008,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.88490956874977,\"longitude_\":100.12672087342608,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.885302490381278,\"longitude_\":100.12667304829165,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.885521440240353,\"longitude_\":100.1266801970379,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.885748782438256,\"longitude_\":100.12673442989593,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.886184311775366,\"longitude_\":100.12689928223388,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.886371044711435,\"longitude_\":100.12693222015717,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.886556923046193,\"longitude_\":100.12691593845197,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.887058969863556,\"longitude_\":100.1267783886852,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.887547354704896,\"longitude_\":100.12664214250168,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.887745630547965,\"longitude_\":100.12661296296805,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.887952855908765,\"longitude_\":100.12663469253742,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.88838254724211,\"longitude_\":100.1267432660041,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.88867177268486,\"longitude_\":100.12674878070436,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.888948154040733,\"longitude_\":100.12668867979535,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.889119678251383,\"longitude_\":100.12661519197152,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.88965548111457,\"longitude_\":100.12632103004057,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.890440398289833,\"longitude_\":100.12572932612804,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.890595726487316,\"longitude_\":100.12569393173928,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.89083685708941,\"longitude_\":100.12572825271758,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.89092017694698,\"longitude_\":100.12571880871474,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.891037856897587,\"longitude_\":100.12567497177714,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.891761687561317,\"longitude_\":100.12513259535619,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.891885118463794,\"longitude_\":100.1250643533811,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.89201181287785,\"longitude_\":100.1250211908644,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.892633993404484,\"longitude_\":100.12487357365991,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.892723272763575,\"longitude_\":100.12483263537747,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.892820100842155,\"longitude_\":100.12471361851891,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.89291347694438,\"longitude_\":100.12434808103623,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.892985029043015,\"longitude_\":100.12422953782732,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.89308490178189,\"longitude_\":100.12416612695728,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.893360731467585,\"longitude_\":100.12410368114618,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.894308353220502,\"longitude_\":100.12396602611501,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.895020251951685,\"longitude_\":100.12387330229565,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.895317877980734,\"longitude_\":100.12387135197324,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0" + + + " }\n" + + " ]\n" + + "}"; + + public static void converToRouteData(){ + List list = new ArrayList<>(); + + try { + JSONObject jsonObject = new JSONObject(jsonStr); + JSONArray jsonElements = jsonObject.getJSONArray("models"); + for (int i = 0; i < jsonElements.length(); i++) { + JSONObject s = jsonElements.getJSONObject(i); + MessagePad.Location.Builder builder = MessagePad.Location.newBuilder(); + builder.setLatitude(s.getDouble("latitude_")); + builder.setLongitude(s.getDouble("longitude_")); + list.add(builder.build()); + } + BusPassengerModel.getInstance().updateRoutePoints(list); + BusPassengerModel.getInstance().startRemainRouteInfo(); + BusPassengerModel.getInstance().startToRouteAndWipe(); + } catch (JSONException e) { + e.printStackTrace(); + } + } +} diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bg_bus_p_arrived_station.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bg_bus_p_arrived_station.png new file mode 100644 index 0000000000..f47f628224 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bg_bus_p_arrived_station.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_arrow_nor.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_arrow_nor.png new file mode 100644 index 0000000000..d8d0663d02 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_arrow_nor.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_auto_nor.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_auto_nor.png new file mode 100644 index 0000000000..c9daea21c9 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_auto_nor.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_light_green_nor.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_light_green_nor.png new file mode 100644 index 0000000000..939d5c0214 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_light_green_nor.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_light_red_nor.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_light_red_nor.png new file mode 100644 index 0000000000..97d774140a Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_light_red_nor.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_light_yellow_nor.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_light_yellow_nor.png new file mode 100644 index 0000000000..a782062c34 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_light_yellow_nor.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_line_blue.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_line_blue.png new file mode 100755 index 0000000000..233be50bd5 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_line_blue.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_line_green.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_line_green.png new file mode 100755 index 0000000000..902cd19c2f Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_line_green.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_line_grey.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_line_grey.png new file mode 100644 index 0000000000..b16a3dd0b8 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_line_grey.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_arrow_arrived.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_arrow_arrived.png new file mode 100644 index 0000000000..445906d280 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_arrow_arrived.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_arrow_un_arrive.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_arrow_un_arrive.png new file mode 100644 index 0000000000..99d8bd7b56 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_arrow_un_arrive.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_car.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_car.png new file mode 100644 index 0000000000..17beb894a6 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_car.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_view_dir_end_point.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_view_dir_end_point.png new file mode 100644 index 0000000000..1e64713481 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_view_dir_end_point.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_view_dir_way_point.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_view_dir_way_point.png new file mode 100644 index 0000000000..ff04c01f13 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_map_view_dir_way_point.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_mogo_nor.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_mogo_nor.png new file mode 100755 index 0000000000..3a779659d3 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_mogo_nor.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_no_order_data.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_no_order_data.png new file mode 100755 index 0000000000..a1a5aed070 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_no_order_data.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_point_blue.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_point_blue.png new file mode 100755 index 0000000000..bc88e93c1d Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_point_blue.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_point_gray.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_point_gray.png new file mode 100755 index 0000000000..ca325eb42e Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_point_gray.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_point_green.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_point_green.png new file mode 100755 index 0000000000..865097cbad Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_point_green.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_un_auto_nor.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_un_auto_nor.png new file mode 100644 index 0000000000..528cd4dc66 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/bus_p_un_auto_nor.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/station_arrow.png b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/station_arrow.png new file mode 100644 index 0000000000..114c7a2ba7 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable-nodpi/station_arrow.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bg_bus_p_end_station_circle.xml b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bg_bus_p_end_station_circle.xml new file mode 100644 index 0000000000..528233f84c --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bg_bus_p_end_station_circle.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bg_bus_p_end_tag_bg.xml b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bg_bus_p_end_tag_bg.xml new file mode 100644 index 0000000000..ca8ad81fe2 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bg_bus_p_end_tag_bg.xml @@ -0,0 +1,14 @@ + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bg_bus_p_middle_station_circle.xml b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bg_bus_p_middle_station_circle.xml new file mode 100644 index 0000000000..4dca66c4fe --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bg_bus_p_middle_station_circle.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bg_bus_p_start_station_circle.xml b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bg_bus_p_start_station_circle.xml new file mode 100644 index 0000000000..97458b6d07 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bg_bus_p_start_station_circle.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bg_bus_p_start_tag_bg.xml b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bg_bus_p_start_tag_bg.xml new file mode 100644 index 0000000000..7a6d44a4c8 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bg_bus_p_start_tag_bg.xml @@ -0,0 +1,14 @@ + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bg_bus_p_traffic_light_background.xml b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bg_bus_p_traffic_light_background.xml new file mode 100644 index 0000000000..6382b0256a --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bg_bus_p_traffic_light_background.xml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bus_p_dividing_line_bg.xml b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bus_p_dividing_line_bg.xml new file mode 100644 index 0000000000..d5d41809d0 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bus_p_dividing_line_bg.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bus_p_panel_cur_station_panel.xml b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bus_p_panel_cur_station_panel.xml new file mode 100644 index 0000000000..9cc2472376 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bus_p_panel_cur_station_panel.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bus_p_route_bg.xml b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bus_p_route_bg.xml new file mode 100644 index 0000000000..94dd7c0007 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bus_p_route_bg.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bus_progress_bar_bg.xml b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bus_progress_bar_bg.xml new file mode 100644 index 0000000000..aa1eeaecd0 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/bus_progress_bar_bg.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/progress_item_round.xml b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/progress_item_round.xml new file mode 100644 index 0000000000..2d74f8fd54 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/drawable/progress_item_round.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/layout/bus_p_base_fragment.xml b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/layout/bus_p_base_fragment.xml new file mode 100644 index 0000000000..608ac59429 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/layout/bus_p_base_fragment.xml @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/layout/bus_p_map_view.xml b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/layout/bus_p_map_view.xml new file mode 100644 index 0000000000..d9fadd6ef5 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/layout/bus_p_map_view.xml @@ -0,0 +1,12 @@ + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/layout/bus_p_no_data_common_view.xml b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/layout/bus_p_no_data_common_view.xml new file mode 100644 index 0000000000..2eefe569cf --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/layout/bus_p_no_data_common_view.xml @@ -0,0 +1,28 @@ + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/layout/bus_p_route_fragment.xml b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/layout/bus_p_route_fragment.xml new file mode 100644 index 0000000000..8567a7a783 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/layout/bus_p_route_fragment.xml @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/layout/bus_p_stations_common_item.xml b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/layout/bus_p_stations_common_item.xml new file mode 100644 index 0000000000..33dfb22485 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/layout/bus_p_stations_common_item.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/layout/bus_p_traffic_light_view.xml b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/layout/bus_p_traffic_light_view.xml new file mode 100644 index 0000000000..5a0db32bc0 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/layout/bus_p_traffic_light_view.xml @@ -0,0 +1,37 @@ + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/values/colors.xml b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/values/colors.xml new file mode 100644 index 0000000000..8e63faf83d --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/values/colors.xml @@ -0,0 +1,30 @@ + + + #2D3E5F + #CCE9EFFC + #C7D2E1 + #2D3E5F + #0043FF + #2D3E5F + #596A8A + #D8E5F8 + #FFB327 + #2D3E5F + #0043FF + #276AFE + #0043FF + #276AFE + #FFC125 + #FF8131 + #31BFF2 + #3257E9 + #FFFFFF + #CDDBF6 + #2D3E5F + #0043FF + #2D3E5F + #E6E9EFFC + #33394C63 + #2D3E5F + #33394C63 + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/values/dimens.xml b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/values/dimens.xml new file mode 100644 index 0000000000..e738022b0d --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/values/dimens.xml @@ -0,0 +1,61 @@ + + + 700dp + 40dp + 40dp + 40dp + 40dp + 110dp + 224dp + 510dp + 3dp + + 158dp + 90dp + 45dp + 158dp + 90dp + 45dp + 90dp + 90dp + 3dp + + 224dp + 50dp + 50dp + 44dp + 130dp + 38dp + + 36dp + + 110dp + 42dp + + 4dp + 10dp + 20dp + 60dp + 30dp + 20dp + 50dp + 6dp + 50dp + 36dp + 80dp + 100dp + 80dp + 60dp + 6dp + + 685dp + 309dp + 50dp + 10dp + 44dp + 55dp + 40dp + + 584dp + 550dp + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/values/strings.xml b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/values/strings.xml new file mode 100644 index 0000000000..e98feed5f5 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/jinlvvan/res/values/strings.xml @@ -0,0 +1,13 @@ + + + KM/H + 您已收车 + 暂无班次 + + + 到达站: + 下一站: + 始发站: + 请携带好随身物品下车。 + 欢迎乘坐蘑菇车联自动驾驶车。 + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/AndroidManifest.xml b/OCH/mogo-och-shuttle-passenger/src/m2/AndroidManifest.xml new file mode 100644 index 0000000000..c3b74bd86a --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/assets/m2_map_style.data b/OCH/mogo-och-shuttle-passenger/src/m2/assets/m2_map_style.data new file mode 100644 index 0000000000..76641add90 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/assets/m2_map_style.data differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/assets/m2_map_style_extra.data b/OCH/mogo-och-shuttle-passenger/src/m2/assets/m2_map_style_extra.data new file mode 100644 index 0000000000..4bed4023d5 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/assets/m2_map_style_extra.data differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/BPRouteDataTestUtils.java b/OCH/mogo-och-shuttle-passenger/src/m2/java/BPRouteDataTestUtils.java new file mode 100644 index 0000000000..6af58e3bb1 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/BPRouteDataTestUtils.java @@ -0,0 +1,56 @@ +import com.mogo.och.bus.passenger.model.PM2DrivingModel; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.List; + +import mogo.telematics.pad.MessagePad; + +/** + * @author: wangmingjun + * @date: 2022/4/13 + */ +public class BPRouteDataTestUtils { + + //13号路口起-13号路口终 +// static String jsonStr ="{\n" + +// " \"models\": [\n" + +// " {\n" + +// " \"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19927760268911,\"lon\":116.73512607061035,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19927736555187,\"lon\":116.73498243020299,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19927135941599,\"lon\":116.73482951462647,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199260672670036,\"lon\":116.73468429259535,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199251260349946,\"lon\":116.73453933465,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19924691997577,\"lon\":116.7343756435551,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199247953493625,\"lon\":116.73421240809087,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19924986849947,\"lon\":116.73400425509712,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199249431152175,\"lon\":116.73378579041055,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199248921305724,\"lon\":116.73357811807278,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19925012387371,\"lon\":116.73337650020184,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199252270195075,\"lon\":116.73318223781153,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.1992521615169,\"lon\":116.73298632625203,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19925202633083,\"lon\":116.73279582043983,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199261230205735,\"lon\":116.73263403473568,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199327991681926,\"lon\":116.73251962434813,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19944850496711,\"lon\":116.73249661840195,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199582026896415,\"lon\":116.73251038561487,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199743326352014,\"lon\":116.73253087453938,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199908347167394,\"lon\":116.73255070500186,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200065950595445,\"lon\":116.7325720694418,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20022747460407,\"lon\":116.73259461416663,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200384057310536,\"lon\":116.73261575018056,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20053849777916,\"lon\":116.73263451936387,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200696919444624,\"lon\":116.7326540541723,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2008524952796,\"lon\":116.7326743511824,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20101429705625,\"lon\":116.73269393580199,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20118279997041,\"lon\":116.73271564378308,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201342388452076,\"lon\":116.73273653366076,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201476063822355,\"lon\":116.73275292393079,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20163479199852,\"lon\":116.73277440686762,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20181243476041,\"lon\":116.7328052766508,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201991767093304,\"lon\":116.7328453845644,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20215573733484,\"lon\":116.73287624009339,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202313648759784,\"lon\":116.73289887933315,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202434745374454,\"lon\":116.7329182210956,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20253164952098,\"lon\":116.73297539811277,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20258043275509,\"lon\":116.73312335324984,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20258233576585,\"lon\":116.73331077089557,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20257107560234,\"lon\":116.73351244039137,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202561578580514,\"lon\":116.73370176209845,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20256256788661,\"lon\":116.73391325024126,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20255633158834,\"lon\":116.73413195000244,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202543311179575,\"lon\":116.73436614303907,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20253067346457,\"lon\":116.73458032609663,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20251776111356,\"lon\":116.73477082198242,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202503997557805,\"lon\":116.73498624001282,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20249129260376,\"lon\":116.73518976336872,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247877796589,\"lon\":116.73537786253135,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20246651610268,\"lon\":116.73559239130266,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20245754388014,\"lon\":116.73574239922202,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20244749208,\"lon\":116.73589674090469,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243806550113,\"lon\":116.73607057284322,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243550556816,\"lon\":116.73628106525871,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243654127756,\"lon\":116.7364949950665,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243738221016,\"lon\":116.7367061649993,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243672476754,\"lon\":116.73691115930336,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243590788176,\"lon\":116.73710722104272,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202436434375336,\"lon\":116.73730688607075,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243749821501,\"lon\":116.73750140347998,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243625962803,\"lon\":116.73771330926793,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202434515480725,\"lon\":116.73791895606205,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2024326561388,\"lon\":116.73815206945737,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243092086137,\"lon\":116.73838655528765,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202430876006126,\"lon\":116.73861890759498,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20242914053177,\"lon\":116.73882029918758,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20242843336561,\"lon\":116.73904465495175,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20242661219026,\"lon\":116.73922453252953,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202426462811076,\"lon\":116.7393708046956,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20242687134937,\"lon\":116.73954685547025,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20242694967377,\"lon\":116.73975021183773,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202424630601236,\"lon\":116.73999740812975,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202422502184625,\"lon\":116.74028266774337,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202419634158936,\"lon\":116.7405942561498,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241975959762,\"lon\":116.7409069557092,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241920524113,\"lon\":116.74120156191647,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241765540262,\"lon\":116.74149288504978,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241569149764,\"lon\":116.7418080096762,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202414529497084,\"lon\":116.74210262897205,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241419532155,\"lon\":116.74241767661879,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202413879360954,\"lon\":116.7427571218185,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241287045245,\"lon\":116.7431284691325,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241214965105,\"lon\":116.74343354359334,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241141271715,\"lon\":116.7437220210538,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2024080520075,\"lon\":116.74399113498052,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202391714280026,\"lon\":116.74427625698272,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20238163805639,\"lon\":116.74452083315958,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202379293010274,\"lon\":116.74475703837204,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202379007817086,\"lon\":116.7449961645494,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20237814181231,\"lon\":116.7452036063558,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202375477619896,\"lon\":116.74539567654291,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2023632396621,\"lon\":116.74555457589031,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20229396554444,\"lon\":116.7456716047369,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20217800547467,\"lon\":116.74574081942625,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202047498095304,\"lon\":116.74573659255675,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20188573786706,\"lon\":116.74571018281719,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201738240263026,\"lon\":116.74568463148606,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20157507049073,\"lon\":116.74565525041498,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20137985142042,\"lon\":116.745619970576,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201187335613575,\"lon\":116.74558631350607,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20098251429043,\"lon\":116.74555055587679,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2007748533628,\"lon\":116.74551426934663,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20057082986032,\"lon\":116.74547749663195,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20036944224329,\"lon\":116.74544156175533,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20016365229035,\"lon\":116.74540577510051,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.1999958572445,\"lon\":116.74537505807076,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19984100521566,\"lon\":116.7453433678602,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.1996863960282,\"lon\":116.74529675648621,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19953919567943,\"lon\":116.74525916493474,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19940587189373,\"lon\":116.74523402869453,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19929047792381,\"lon\":116.74518617038383,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922141745155,\"lon\":116.74506912884067,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19920798885308,\"lon\":116.744896716334,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19920912644279,\"lon\":116.74467216715483,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199209186509314,\"lon\":116.74448257515108,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19920910709997,\"lon\":116.74430613406223,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.1992100786082,\"lon\":116.74410888316238,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19921081961254,\"lon\":116.74391968819582,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19921040855518,\"lon\":116.7437082083402,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19921085053439,\"lon\":116.74346931155634,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19921197237373,\"lon\":116.74325149697013,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19921248248983,\"lon\":116.74301103786591,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.1992139724646,\"lon\":116.74277237066539,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199215818352386,\"lon\":116.74253219408898,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199216175018876,\"lon\":116.74228853120842,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199215970354246,\"lon\":116.74204663206451,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199216627492966,\"lon\":116.74183871233049,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19921789170398,\"lon\":116.74165788334192,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922000138535,\"lon\":116.74144512197054,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199221559127494,\"lon\":116.741249370491,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922287231889,\"lon\":116.7410525810756,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922229019589,\"lon\":116.74085266662037,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.1992216995901,\"lon\":116.74061957723823,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922263073874,\"lon\":116.74041638149129,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922478093337,\"lon\":116.7402123910757,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199227066091595,\"lon\":116.74003419421553,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199228634241756,\"lon\":116.73985841944678,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922951636012,\"lon\":116.7397079274105,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199252095329484,\"lon\":116.73956265582487,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199346162997905,\"lon\":116.73944690416265,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199470799628024,\"lon\":116.73941941053417,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19962513314346,\"lon\":116.7394280706812,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199780626058924,\"lon\":116.73944255215424,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199961525343376,\"lon\":116.73945856750177,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20016196947193,\"lon\":116.73947572081121,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200384479551936,\"lon\":116.7394949225795,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200595083817475,\"lon\":116.73951027963179,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200792203321086,\"lon\":116.73952526850614,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200985930701684,\"lon\":116.73954125209579,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20115978977055,\"lon\":116.73955610094161,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201321019536124,\"lon\":116.7395695239138,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20147117943043,\"lon\":116.7395823299481,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20163699848565,\"lon\":116.73959633422596,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20178484338371,\"lon\":116.7396085776486,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201962185646316,\"lon\":116.73962351991214,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2021018923927,\"lon\":116.7396354059821,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2022137620686,\"lon\":116.73964348380458,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20232600820075,\"lon\":116.73961190446633,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241090270993,\"lon\":116.73951649703137,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20245777783807,\"lon\":116.73937664238166,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20246906634823,\"lon\":116.73920146119093,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202470916682884,\"lon\":116.73898763065634,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247034830421,\"lon\":116.73878158418357,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20246978204673,\"lon\":116.73857680142473,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247082638905,\"lon\":116.73834517890637,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202471943178196,\"lon\":116.7381047689514,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247131648035,\"lon\":116.73787761484981,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202470799473765,\"lon\":116.73766230702478,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247013054322,\"lon\":116.73743619407796,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20246999515433,\"lon\":116.73724916823292,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247199652478,\"lon\":116.73704888970806,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202473960263525,\"lon\":116.73684083235807,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202474504753205,\"lon\":116.73665462440796,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247501354581,\"lon\":116.73650710371837,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20246541231906,\"lon\":116.73635807696789,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202426768984274,\"lon\":116.73622283382787,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20236638788854,\"lon\":116.73610589402243,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20227106919894,\"lon\":116.73600895001849,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2021428343084,\"lon\":116.73596816020945,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20197815580698,\"lon\":116.73594623645097,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20181789535303,\"lon\":116.73593148707488,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201667906886954,\"lon\":116.73591743008926,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201505897730755,\"lon\":116.7359002912543,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20135083580946,\"lon\":116.73588579696379,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20118617904595,\"lon\":116.73586970398149,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20102374028594,\"lon\":116.73585314703226,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20085554043743,\"lon\":116.73583763953049,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20069451888229,\"lon\":116.73582073901778,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200530837344964,\"lon\":116.73580314359012,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2003608457064,\"lon\":116.73578183888779,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20021770046798,\"lon\":116.73575292592922,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20003454701824,\"lon\":116.7357174959358,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19986125116602,\"lon\":116.73569499961796,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19969408518737,\"lon\":116.73567725223492,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19955533048882,\"lon\":116.73566375985422,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19943174810538,\"lon\":116.73564927714162,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19933167546824,\"lon\":116.735595995086,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199280357603875,\"lon\":116.73546293260645,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19927848361656,\"lon\":116.73531579486274,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19928127892504,\"lon\":116.73505848474375,\"speed\": 0.0\n" + +// " }\n" + +// " ]\n" + +// "}"; + + //洱海轨迹 + static String jsonStr ="{\n" + + " \"models\": [\n" + + " {\n" + + "\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87506159122434,\"longitude_\":100.13463113454593,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874963432017065,\"longitude_\":100.13431083742782,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87481475105022,\"longitude_\":100.13402921175965,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874646001578594,\"longitude_\":100.13381071517328,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874280379177108,\"longitude_\":100.13344505101841,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87422474353087,\"longitude_\":100.13336522063217,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.8741846037573,\"longitude_\":100.13326081770579,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874169301193604,\"longitude_\":100.133157732712,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87417865388365,\"longitude_\":100.13305383003687,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87424355168725,\"longitude_\":100.13288988207758,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87441186213399,\"longitude_\":100.1326293335985,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874490698935094,\"longitude_\":100.13247594955229,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874551609777672,\"longitude_\":100.13227787460397,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874574232444672,\"longitude_\":100.1320943662068,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874574936235152,\"longitude_\":100.13109176087639,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874553271326842,\"longitude_\":100.13095333429315,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874468877309848,\"longitude_\":100.1307193884582,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874449652750723,\"longitude_\":100.1306199898516,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874449487671647,\"longitude_\":100.13046154976821,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87448439242463,\"longitude_\":100.13030173580755,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874554236422213,\"longitude_\":100.13013644761386,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874657614202334,\"longitude_\":100.1299792051648,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.874777620037,\"longitude_\":100.12985830283493,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.8749211786138,\"longitude_\":100.12975642056448,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.875123187810807,\"longitude_\":100.12965486650492,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.875282658783302,\"longitude_\":100.12960819854966,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87555277290776,\"longitude_\":100.12954493830546,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.875686392944456,\"longitude_\":100.12948797177033,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87609150201856,\"longitude_\":100.12914349760804,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87645852877848,\"longitude_\":100.1289124421148,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87667085149294,\"longitude_\":100.1288070141346,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.877063427631544,\"longitude_\":100.12866094818,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87751767381502,\"longitude_\":100.1286538378911,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87776644058061,\"longitude_\":100.12861180318971,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.87866240134362,\"longitude_\":100.12843614360035,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.879103098247672,\"longitude_\":100.12837521690956,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.879326467139197,\"longitude_\":100.12832846342278,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.8800083487784,\"longitude_\":100.12811951944514,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.88019070137511,\"longitude_\":100.12802255167708,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.880357426115513,\"longitude_\":100.12787083439976,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.880481954487596,\"longitude_\":100.1276940858994,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.880653097994426,\"longitude_\":100.12740127585158,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.880758517533007,\"longitude_\":100.12730743064938,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.880799507331627,\"longitude_\":100.12724835914499,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.88098572681533,\"longitude_\":100.12658255210448,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.881039332211476,\"longitude_\":100.1263847771375,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.881100185621683,\"longitude_\":100.12625820340021,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.881198711287677,\"longitude_\":100.12611952057267,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.88133930457031,\"longitude_\":100.12599337741426,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.881467122690022,\"longitude_\":100.12592180492642,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.88159423650277,\"longitude_\":100.12588048516646,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.882012210316635,\"longitude_\":100.12584119198453,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.88240347787595,\"longitude_\":100.12581569076075,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.882530989675523,\"longitude_\":100.1258417579907,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.88266718412272,\"longitude_\":100.1258996456634,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.882846062879587,\"longitude_\":100.12604302069693,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.883143169798704,\"longitude_\":100.12643363872347,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.883316147374213,\"longitude_\":100.12660436351877,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.883516631635977,\"longitude_\":100.12670006660859,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.884412161186358,\"longitude_\":100.12681096840119,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.88456077756699,\"longitude_\":100.12680626559008,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.88490956874977,\"longitude_\":100.12672087342608,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.885302490381278,\"longitude_\":100.12667304829165,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.885521440240353,\"longitude_\":100.1266801970379,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.885748782438256,\"longitude_\":100.12673442989593,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.886184311775366,\"longitude_\":100.12689928223388,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.886371044711435,\"longitude_\":100.12693222015717,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.886556923046193,\"longitude_\":100.12691593845197,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.887058969863556,\"longitude_\":100.1267783886852,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.887547354704896,\"longitude_\":100.12664214250168,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.887745630547965,\"longitude_\":100.12661296296805,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.887952855908765,\"longitude_\":100.12663469253742,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.88838254724211,\"longitude_\":100.1267432660041,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.88867177268486,\"longitude_\":100.12674878070436,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.888948154040733,\"longitude_\":100.12668867979535,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.889119678251383,\"longitude_\":100.12661519197152,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.88965548111457,\"longitude_\":100.12632103004057,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.890440398289833,\"longitude_\":100.12572932612804,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.890595726487316,\"longitude_\":100.12569393173928,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.89083685708941,\"longitude_\":100.12572825271758,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.89092017694698,\"longitude_\":100.12571880871474,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.891037856897587,\"longitude_\":100.12567497177714,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.891761687561317,\"longitude_\":100.12513259535619,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.891885118463794,\"longitude_\":100.1250643533811,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.89201181287785,\"longitude_\":100.1250211908644,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.892633993404484,\"longitude_\":100.12487357365991,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.892723272763575,\"longitude_\":100.12483263537747,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.892820100842155,\"longitude_\":100.12471361851891,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.89291347694438,\"longitude_\":100.12434808103623,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.892985029043015,\"longitude_\":100.12422953782732,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.89308490178189,\"longitude_\":100.12416612695728,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.893360731467585,\"longitude_\":100.12410368114618,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.894308353220502,\"longitude_\":100.12396602611501,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.895020251951685,\"longitude_\":100.12387330229565,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0},{\"altitude_\":0.0,\"heading_\":0.0,\"latitude_\":25.895317877980734,\"longitude_\":100.12387135197324,\"memoizedIsInitialized\":-1,\"unknownFields\":{\"fields\":{},\"fieldsDescending\":{}},\"memoizedSize\":-1,\"memoizedHashCode\":0" + + + " }\n" + + " ]\n" + + "}"; + + public static void converToRouteData(){ + List list = new ArrayList<>(); + + try { + JSONObject jsonObject = new JSONObject(jsonStr); + JSONArray jsonElements = jsonObject.getJSONArray("models"); + for (int i = 0; i < jsonElements.length(); i++) { + JSONObject s = jsonElements.getJSONObject(i); + MessagePad.Location.Builder builder = MessagePad.Location.newBuilder(); + builder.setLatitude(s.getDouble("latitude_")); + builder.setLongitude(s.getDouble("longitude_")); + list.add(builder.build()); + } + PM2DrivingModel.Companion.getINSTANCE().updateRoutePoints(list); + + } catch (JSONException e) { + e.printStackTrace(); + } + } +} diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/BusPassengerM2.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/BusPassengerM2.kt new file mode 100644 index 0000000000..de9937f0c7 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/BusPassengerM2.kt @@ -0,0 +1,92 @@ +package com.mogo.och.bus.passenger + +import android.content.Context +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentActivity +import com.alibaba.android.arouter.facade.annotation.Route +import com.mogo.commons.module.status.IMogoStatusChangedListener +import com.mogo.commons.module.status.MogoStatusManager +import com.mogo.commons.module.status.StatusDescriptor +import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager.getMapUIController +import com.mogo.eagle.core.function.call.setting.CallerMoGoUiSettingManager.stepInDayMode +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.och.bus.passenger.constant.BusPassengerConst +import com.mogo.och.bus.passenger.ui.PM2BaseFragment + +/** + * 网约车-Bus-乘客端 + * + * Created on 2022/3/29 + */ +@Route(path = BusPassengerConst.PATH) +class MogoOCHBusPassenger : IMogoOCH, IMogoStatusChangedListener { + private var mActivity: FragmentActivity? = null + private var mContainerId = 0 + private var mPM2Fragment: PM2BaseFragment? = null + override fun createCoverage(activity: FragmentActivity, containerId: Int) {} + override fun createCoverage(activity: FragmentActivity?, containerId: Int?): Fragment? { + mActivity = activity + mContainerId = containerId!! +// if (MogoStatusManager.getInstance().isScreenCoverDismiss){ + showFragment() +// }else{ +// MogoStatusManager.getInstance() +// .registerStatusChangedListener("ochM2Passenger", StatusDescriptor.SCREEN_COVER, this) +// } + return null + } + + override val functionName: String + get() = "och-bus-passenger-m2" + + override fun onDestroy() { + // 若不调用finish, 设置中打开关闭UITouch,会造成och fragment 重叠 + mActivity?.finish() + } + + override fun init(context: Context) { + } + + /** + * 进入鹰眼模式,设置手势缩放地图失效 + */ + private fun stepIntoVrMode() { + d(SceneConstant.M_TAXI_P + TAG, "进入vr模式") + getMapUIController()?.stepInVrMode(true) // 白天模式 + stepInDayMode() //白天模式 状态栏字体颜色变黑 + } + + private fun showFragment() { + if (mPM2Fragment == null) { + d(SceneConstant.M_TAXI_P + TAG, "准备add fragment======") + mPM2Fragment = PM2BaseFragment() + mActivity?.supportFragmentManager?.beginTransaction() + ?.add(mContainerId, mPM2Fragment!!)?.commitAllowingStateLoss() + } + d(SceneConstant.M_TAXI_P + TAG, "准备show fragment") + mActivity?.supportFragmentManager?.beginTransaction()?.show(mPM2Fragment!!) + ?.commitAllowingStateLoss() + } + + private fun hideFragment() { + if (mPM2Fragment != null) { + mActivity?.supportFragmentManager?.beginTransaction()?.hide(mPM2Fragment!!) + ?.commitAllowingStateLoss() + } + } + + companion object { + private val TAG = MogoOCHBusPassenger::class.java.simpleName + } + + override fun onStatusChanged(descriptor: StatusDescriptor?, isTrue: Boolean) { + if (descriptor == StatusDescriptor.SCREEN_COVER){ + if (isTrue){ + showFragment() + }else{ + hideFragment() + } + } + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/bean/PM2OperationStatusResponse.java b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/bean/PM2OperationStatusResponse.java new file mode 100644 index 0000000000..9869a9e135 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/bean/PM2OperationStatusResponse.java @@ -0,0 +1,21 @@ +package com.mogo.och.bus.passenger.bean; + +import com.mogo.eagle.core.data.BaseData; + +/** + * @author congtaowang + * @since 2021/3/22 + * + * 小巴车运营状态返回参数 + */ +public class PM2OperationStatusResponse extends BaseData { + + public Result data; + + public static class Result { + private String sn; //司机屏sn + private String phone; //司机手机号 + public String plateNumber; //车牌号 + public int driverStatus;//0:已收车,1:已出车 + } +} diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/bean/PM2QueryLineRequest.java b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/bean/PM2QueryLineRequest.java new file mode 100644 index 0000000000..5569730773 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/bean/PM2QueryLineRequest.java @@ -0,0 +1,16 @@ +package com.mogo.och.bus.passenger.bean; + +public +/** + * @author congtaowang + * @since 2021/3/22 + * + * 根据车机行驶线路站点信息 + */ +class PM2QueryLineRequest { + + private String sn; + public PM2QueryLineRequest(String sn) { + this.sn = sn; + } +} diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/bean/PM2RoutesResponse.java b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/bean/PM2RoutesResponse.java new file mode 100644 index 0000000000..207b2d7e7d --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/bean/PM2RoutesResponse.java @@ -0,0 +1,28 @@ +package com.mogo.och.bus.passenger.bean; + +import com.mogo.eagle.core.data.BaseData; + +/** + * 网约车小巴路线接口请求响应结果 返回的是对应司机屏的线路信息 + * + * @author tongchenfei + */ +public class PM2RoutesResponse extends BaseData { + private PM2RoutesResult data; + + public PM2RoutesResult getResult() { + return data; + } + + public void setResult(PM2RoutesResult data) { + this.data = data; + } + + @Override + public String toString() { + return "OchBusRoutesResponse{" + + "data=" + data + + '}'; + } + +} diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/bean/PM2RoutesResult.java b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/bean/PM2RoutesResult.java new file mode 100644 index 0000000000..1f26b5346d --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/bean/PM2RoutesResult.java @@ -0,0 +1,79 @@ +package com.mogo.och.bus.passenger.bean; + +import java.util.List; +import java.util.Objects; + +/** + * 网约车小巴路线接口返回接口数据封装 + * + * @author tongchenfei + */ +public class PM2RoutesResult { + private List sites; + private int lineId; + private String name; //线路名称 + private int lineType; //线路类型,0:环形 + private String description; + private int status; + private String runningDur; //运营时间 + private long taskTime; //线路时间班次 + + public List getSites() { + return sites; + } + + public int getLineId() { + return lineId; + } + + public String getName() { + return name; + } + + public int getLineType() { + return lineType; + } + + public String getDescription() { + return description; + } + + public int getStatus() { + return status; + } + + public String getRunningDur() { + return runningDur; + } + + @Override + public String toString() { + return "BusPassengerRoutesResult{" + + "sites=" + sites + + ", lineId=" + lineId + + ", name='" + name + '\'' + + ", lineType=" + lineType + + ", description='" + description + '\'' + + ", status=" + status + + ", runningDur='" + runningDur + '\'' + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PM2RoutesResult that = (PM2RoutesResult) o; + return lineId == that.lineId + && lineType == that.lineType + && status == that.status + && sites.equals(that.sites) + && name.equals(that.name) + && runningDur.equals(that.runningDur); + } + + @Override + public int hashCode() { + return Objects.hash(sites, lineId, name, lineType, description, status, runningDur); + } +} diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/bean/PM2Station.java b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/bean/PM2Station.java new file mode 100644 index 0000000000..ec903b7e93 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/bean/PM2Station.java @@ -0,0 +1,173 @@ +package com.mogo.och.bus.passenger.bean; + +import java.util.Objects; + +/** + * 单个网约车小巴车站信息 + * + * @author wangmingjun + */ +public class PM2Station { + + private String name; + private String description; + private String cityCode; + private double lon; //高精坐标 + private double lat; //高精坐标 + private double gcjLon; //高德坐标 + private double gcjLat; //高德坐标 + private int businessType; //站点类型,9:taxi,10:bus + 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 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 double getGcjLon() { + return gcjLon; + } + + public double getGcjLat() { + return gcjLat; + } + + 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 "OchBusStation{" + + "name='" + name + '\'' + + ", description='" + description + '\'' + + ", cityCode='" + cityCode + '\'' + + ", lon=" + lon + + ", lat=" + lat + + ", businessType=" + businessType + + ", status=" + status + + ", siteId=" + siteId + + ", seq=" + seq + + ", drivingStatus=" + drivingStatus + + ", ifStop=" + ifStop + + ", leaving=" + leaving + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PM2Station that = (PM2Station) o; + return Double.compare(that.lon, lon) == 0 + && Double.compare(that.lat, lat) == 0 + && Double.compare(that.gcjLon, gcjLon) == 0 + && Double.compare(that.gcjLat, gcjLat) == 0 + && businessType == that.businessType + && status == that.status + && siteId == that.siteId + && seq == that.seq + && drivingStatus == that.drivingStatus + && ifStop == that.ifStop + && leaving == that.leaving + && Objects.equals(name, that.name) + && Objects.equals(cityCode, that.cityCode); + } + + @Override + public int hashCode() { + return Objects.hash(name, description, cityCode, lon, lat, gcjLon, gcjLat, businessType, status, siteId, seq, drivingStatus, ifStop, leaving); + } +} diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/callback/ADASCallback.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/callback/ADASCallback.kt new file mode 100644 index 0000000000..217f03740f --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/callback/ADASCallback.kt @@ -0,0 +1,10 @@ +package com.mogo.och.bus.passenger.callback + +/** + * @author: wangmingjun + * @date: 2023/2/15 + */ +interface ADASCallback { + fun updateHDMapStations(stations: MutableList>) + fun removeHDMapStations() +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/callback/AutoPilotStatusCallback.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/callback/AutoPilotStatusCallback.kt new file mode 100644 index 0000000000..efb7410ba2 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/callback/AutoPilotStatusCallback.kt @@ -0,0 +1,14 @@ +package com.mogo.och.bus.passenger.callback + +/** + * @author: wangmingjun + * @date: 2023/2/13 + */ +interface AutoPilotStatusCallback { + /** + * false: 未开启自驾, true : 开启自驾 + */ + fun updateAutoStatus(isOpen: Boolean) + + fun updateAutoStatus(status: Int) +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/callback/DrivingInfoCallback.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/callback/DrivingInfoCallback.kt new file mode 100644 index 0000000000..452ffb685a --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/callback/DrivingInfoCallback.kt @@ -0,0 +1,18 @@ +package com.mogo.och.bus.passenger.callback + +import com.mogo.och.bus.passenger.bean.PM2Station + +/** + * @author: wangmingjun + * @date: 2023/2/2 + */ +interface DrivingInfoCallback { + fun updateSpeed(speed: Int) + fun updatePlateNumber(carNum: String) + fun updateLine(lineName: String, lineDuring: String) + fun updateRemainMT(meters : Long, timeInSecond : Long) // 米,秒 + fun changeOperationStatus(loginStatus : Boolean) + fun showNoTaskView(isTrue : Boolean) + fun updateLineStations(stations: MutableList) + fun updateStationsInfo(stations: MutableList, i: Int, isArrived: Boolean) +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/constant/M2Const.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/constant/M2Const.kt new file mode 100644 index 0000000000..65d482b5fd --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/constant/M2Const.kt @@ -0,0 +1,16 @@ +package com.mogo.och.bus.passenger.constant + +/** + * Created on 2021/12/6 + */ +class M2Const { + companion object { + //站点UUID + const val M2_MAP_STATION_MAKER = "m2_map_station_maker" + + /** + * Marker类型 + */ + const val TYPE_MARKER_M2_LINE = "TYPE_MARKER_M2_LINE" + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/model/PM2ADASModel.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/model/PM2ADASModel.kt new file mode 100644 index 0000000000..a21f2fd938 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/model/PM2ADASModel.kt @@ -0,0 +1,46 @@ +package com.mogo.och.bus.passenger.model + +import android.content.Context +import com.amap.api.maps.model.LatLng +import com.mogo.och.bus.passenger.bean.PM2Station +import com.mogo.och.bus.passenger.callback.ADASCallback + +/** + * @author: wangmingjun + * @date: 2023/2/2 + */ +class PM2ADASModel private constructor() { + + private var mContext: Context? = null + private var mAdasCallback: ADASCallback? = null + + companion object { + val TAG = PM2ADASModel::class.java.simpleName + val INSTANCE: PM2ADASModel by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { + PM2ADASModel() + } + } + + fun init(context : Context){ + this.mContext = context + } + + fun setAdasCallback(adasCallback: ADASCallback?){ + this.mAdasCallback = adasCallback + } + + fun updateHDMapStations(stations: MutableList){ + var stationsList = mutableListOf>() + for (i in stations.indices){ + var listLatLng = mutableListOf() // 0: long 1:lat + listLatLng.add(stations[i].lon) + listLatLng.add(stations[i].lat) + stationsList.add(listLatLng) + } + mAdasCallback?.updateHDMapStations(stationsList) + } + + fun removeHDMapStations(){ + mAdasCallback?.removeHDMapStations() + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/model/PM2DrivingModel.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/model/PM2DrivingModel.kt new file mode 100644 index 0000000000..60f012ba68 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/model/PM2DrivingModel.kt @@ -0,0 +1,530 @@ +package com.mogo.och.bus.passenger.model + +import android.content.Context +import android.media.AudioAttributes +import android.media.AudioFocusRequest +import android.media.AudioManager +import android.net.ConnectivityManager +import android.os.Build +import android.os.Handler +import androidx.annotation.RequiresApi +import com.mogo.commons.module.intent.IMogoIntentListener +import com.mogo.commons.module.intent.IntentManager +import com.mogo.commons.voice.AIAssist +import com.mogo.commons.voice.IMogoVoiceCmdCallBack +import com.mogo.eagle.core.data.autopilot.AutopilotStatusInfo +import com.mogo.eagle.core.data.config.FunctionBuildConfig +import com.mogo.eagle.core.data.map.MogoLocation +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener +import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener +import com.mogo.eagle.core.function.api.autopilot.IMoGoPlanningRottingListener +import com.mogo.eagle.core.function.api.telematic.IReceivedMsgListener +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager +import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager +import com.mogo.eagle.core.function.call.autopilot.CallerPlanningRottingListenerManager +import com.mogo.eagle.core.function.call.telematic.CallerTelematicListenerManager +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d +import com.mogo.eagle.core.utilcode.mogo.logger.Logger +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.eagle.core.utilcode.util.CoordinateUtils +import com.mogo.eagle.core.utilcode.util.GsonUtils +import com.mogo.eagle.core.utilcode.util.NetworkUtils +import com.mogo.eagle.core.utilcode.util.ToastUtils +import com.mogo.och.bus.passenger.R +import com.mogo.och.bus.passenger.bean.PM2OperationStatusResponse +import com.mogo.och.bus.passenger.bean.PM2RoutesResponse +import com.mogo.och.bus.passenger.bean.PM2RoutesResult +import com.mogo.och.bus.passenger.bean.PM2Station +import com.mogo.och.bus.passenger.callback.AutoPilotStatusCallback +import com.mogo.och.bus.passenger.callback.DrivingInfoCallback +import com.mogo.och.bus.passenger.constant.BusPassengerConst +import com.mogo.och.bus.passenger.network.PM2ModelLoopManager +import com.mogo.och.common.module.bean.AppConnectMsg +import com.mogo.och.common.module.biz.common.socketmessage.OCHSocketMessageManager +import com.mogo.och.common.module.biz.network.OchCommonServiceCallback +import com.mogo.och.common.module.biz.constant.OchCommonConst +import com.mogo.och.common.module.utils.CoordinateCalculateRouteUtil +import com.mogo.och.common.module.utils.DateTimeUtil +import mogo.telematics.pad.MessagePad +import kotlin.math.abs + +/** + * @author: wangmingjun + * @date: 2023/1/31 + */ +class PM2DrivingModel private constructor() { + + private var mContext: Context? = null + private var mLocation: MogoLocation? = null + + private var mRoutePoints = mutableListOf() + private var routesResult: PM2RoutesResult? = null + + private var mCurrentAutoStatus = -1 + + var mStations = mutableListOf() + private var mNextStationIndex = 0 // A-B要到达站的index + private var isGoingToNextStation = false //是否前往下一站过程中 + + private var mTwoStationsRouts = mutableListOf() + private var mPreRouteIndex = 0 + private var mWipePreIndex = 0 + + private var mDrivingInfoCallback: DrivingInfoCallback? = null //行程信息 + private var mAutoStatusCallback: AutoPilotStatusCallback? = null //自动驾驶状态 + + private var operationStatus: PM2OperationStatusResponse.Result? = null + + private val handler = Handler(Handler.Callback { msg -> + if (msg.what == MSG_QUERY_BUS_P_STATION) { + queryDriverOperationStatus() + return@Callback true + } + false + }) + + companion object { + val TAG = PM2DrivingModel::class.java.simpleName + const val MSG_QUERY_BUS_P_STATION = 1001 + val INSTANCE: PM2DrivingModel by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { + PM2DrivingModel() + } + } + + fun init(context : Context){ + mContext = context + initListener() + // TODO: 2022/3/31 + queryDriverOperationStatus() + startOrStopOrderLoop(true) + } + + private fun initListener() { + //自动驾驶状态监听 + CallerAutoPilotStatusListenerManager.addListener(TAG, mAutoPilotStatusListener) + + // 定位监听 + CallerChassisLocationGCJ02ListenerManager.addListener(TAG, mMapLocationListener) +// CallerChassisLocationGCJ02ListenerManager.setListenerHz(TAG,2)//设置2hz, 1s返回2次 + + //司乘屏通信监听 + CallerTelematicListenerManager.addListener(TAG,mReceivedMsgListener) + + //自动驾驶轨迹监听 + CallerPlanningRottingListenerManager.addListener(TAG, moGoAutopilotPlanningListener) + + //网络监听 + IntentManager.getInstance().registerIntentListener(ConnectivityManager.CONNECTIVITY_ACTION, mNetWorkIntentListener) + + } + + fun releaseListener(){ + //自动驾驶状态监听 + CallerAutoPilotStatusListenerManager.removeListener(TAG) + + // 定位监听 + CallerChassisLocationGCJ02ListenerManager.removeListener(TAG) + + CallerTelematicListenerManager.removeListener(TAG) + + //自动驾驶轨迹监听 + CallerPlanningRottingListenerManager.removeListener(TAG) + } + + fun setDrivingInfoCallback(drivingInfoCallback : DrivingInfoCallback?){ + mDrivingInfoCallback = drivingInfoCallback + } + + fun setAutoStatusCallback(autoPilotStatusCallback: AutoPilotStatusCallback?){ + mAutoStatusCallback = autoPilotStatusCallback + } + + private val mNetWorkIntentListener = IMogoIntentListener { intentStr, _ -> + if (ConnectivityManager.CONNECTIVITY_ACTION == intentStr) { + if (NetworkUtils.isConnected(mContext)) { + queryDriverOperationStatus() + } + } + } + + private val mReceivedMsgListener: IReceivedMsgListener = + object : IReceivedMsgListener{ + @RequiresApi(Build.VERSION_CODES.O) + override fun onReceivedMsg(type: Int, byteArray: ByteArray) {//接收司机端发来的信息 + if (OchCommonConst.BUSINESS_STRING == type){ + val msg = GsonUtils.fromJson(String(byteArray),AppConnectMsg::class.java) as AppConnectMsg + Logger.d(SceneConstant.M_BUS_P+TAG,"onReceivedMsg = "+GsonUtils.toJson(msg)) + if (msg.isPlay){ //播报 + speakTTS(msg.msg) + } + if (msg.isViewShow){ //消息盒子显示内容 + OCHSocketMessageManager.pushAppOperationalMsgBox( + DateTimeUtil.getCurrentTimeStamp(),msg.msg) + } + } + } + } + + @RequiresApi(Build.VERSION_CODES.O) + private fun speakTTS(msg: String) { + + var mAudioManager = mContext?.getSystemService(Context.AUDIO_SERVICE) as AudioManager + var mAudioAttributes = AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_MEDIA) //设置声音的用途 + .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) //设置声音的类型 + .build() + var mAudioFocusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) //设置焦点类型 + .setAudioAttributes(mAudioAttributes) //设置声音属性 + .setAcceptsDelayedFocusGain(false) //设置接受延迟获取焦点,需要设置OnAudioFocusChangeListener来监听焦点的获取 + .build() + mAudioManager.requestAudioFocus(mAudioFocusRequest) //抢占焦点 + + AIAssist.getInstance(mContext).speakTTSVoiceWithLevel(msg,AIAssist.LEVEL0,object : IMogoVoiceCmdCallBack{ + override fun onSpeakEnd(speakText: String?) { + mAudioManager.abandonAudioFocusRequest(mAudioFocusRequest) + } + + override fun onSpeakError(speakText: String?, errorMsg: String?) { + mAudioManager.abandonAudioFocusRequest(mAudioFocusRequest) + } + + override fun onSpeakSelectTimeOut(speakText: String?) { + mAudioManager.abandonAudioFocusRequest(mAudioFocusRequest) + } + }) + } + + private val mMapLocationListener: IMoGoChassisLocationGCJ02Listener = + object : IMoGoChassisLocationGCJ02Listener{ + override fun onChassisLocationGCJ02(mogoLocation: MogoLocation?) { + if (null == mogoLocation) return + mLocation = mogoLocation + updateSpeed(mogoLocation) + } + } + + private val moGoAutopilotPlanningListener = object : IMoGoPlanningRottingListener{ + override fun onAutopilotRotting(globalPathResp: MessagePad.GlobalPathResp?) { + d(SceneConstant.M_BUS_P + TAG, "och-rotting==globalPathResp = " + GsonUtils.toJson(globalPathResp)) + globalPathResp?.let { + d(SceneConstant.M_BUS_P + TAG, "och-rotting==wayPointsSize = " + it.wayPointsList.size) + updateRoutePoints(it.wayPointsList) + } + } + + } + + fun updateRoutePoints(routePoints: List?) { + mRoutePoints.clear() + val latLngModels = CoordinateCalculateRouteUtil + .coordinateConverterWgsToGcjLocations(mContext, routePoints) + d(SceneConstant.M_BUS_P + TAG, "och-rotting==latLngModels = " + latLngModels.size) + mRoutePoints.addAll(latLngModels) + calculateTwoStationsRoute() + } + + private fun updateSpeed(mogoLocation: MogoLocation) { + // km/h + val speedKM = (abs(mogoLocation.gnssSpeed) * 3.6f).toInt() + + mDrivingInfoCallback?.updateSpeed(speedKM) + } + + private val mAutoPilotStatusListener: IMoGoAutopilotStatusListener = + object : IMoGoAutopilotStatusListener { + + override fun onAutopilotArriveAtStation(arrivalNotification: MessagePad.ArrivalNotification?) { + super.onAutopilotArriveAtStation(arrivalNotification) + } + + override fun onAutopilotStatusResponse(autoPilotStatusInfo: AutopilotStatusInfo) { + super.onAutopilotStatusResponse(autoPilotStatusInfo) + val status = autoPilotStatusInfo.state + if (mCurrentAutoStatus == status) return + d(SceneConstant.M_BUS_P+TAG, "onAutopilotStatusResponse ===== $status") + if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING != status){ + //美化模式下且行程中 + if (FunctionBuildConfig.isDemoMode && + mNextStationIndex>= 0 && mNextStationIndex <= mStations.size - 1 + && isGoingToNextStation){ + mAutoStatusCallback?.updateAutoStatus(true) + }else{//非美化模式下 + mAutoStatusCallback?.updateAutoStatus(false) + } + + }else{//自驾状态 2 + mAutoStatusCallback?.updateAutoStatus(true) + } + mCurrentAutoStatus = status + } + + } + + private fun queryDriverOperationDelay() { + handler.sendEmptyMessageDelayed(MSG_QUERY_BUS_P_STATION, + BusPassengerConst.QUERY_BUS_P_STATION_DELAY + ) + } + + private fun queryDriverOperationStatus() { + mContext?.let { + PM2ServiceManager.queryDriverOperationStatus( + it, + object : OchCommonServiceCallback { + override fun onSuccess(data: PM2OperationStatusResponse?) { + if (data?.data == null) return + if (data.data.driverStatus != operationStatus?.driverStatus + || data.data.plateNumber != operationStatus?.plateNumber){ + d(SceneConstant.M_BUS_P+TAG, "queryDriverOperationStatus ===== 车牌或者登陆状态有变更") + mDrivingInfoCallback?.changeOperationStatus(data.data.driverStatus == 1) + } + operationStatus = data.data as PM2OperationStatusResponse.Result +// mDrivingInfoCallback?.updatePlateNumber(data.data.plateNumber) + } + + override fun onError() { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort(mContext!!.getString(R.string.network_error_tip)) + } else { + ToastUtils.showShort(mContext!!.getString(R.string.request_error_tip)) + } + queryDriverOperationDelay() + } + + override fun onFail(code: Int, msg: String) { + //延迟3s再次查询 + queryDriverOperationDelay() + } + }) + } + } + + fun queryDriverSiteByCoordinate(){ + mContext?.let { + PM2ServiceManager.queryDriverSiteByCoordinate(it, + object : OchCommonServiceCallback{ + override fun onSuccess(data: PM2RoutesResponse?) { + + if (data == null || data.result == null){ + if (routesResult != null) { + routesResult == null + updateLocalOrder() + d(SceneConstant.M_BUS_P+TAG, "queryDriverSiteByCoordinate= result is null") + return + } + return + } + if (data.result != null && data.result.equals(routesResult)){ + d(SceneConstant.M_BUS_P+TAG, "queryDriverSiteByCoordinate= not update") + return + } + + routesResult = data.result + updatePassengerRouteInfo(data.result) + } + + override fun onFail(code: Int, msg: String?) { + d(SceneConstant.M_BUS_P+TAG, "queryDriverSiteByCoordinate = %s", msg) + if (code == 1003){ + queryDriverOperationDelay() + } + if (PM2ServiceManager.driverAppSn.isEmpty()){ + return + } + if (code == 1003) { + routesResult = null + isGoingToNextStation = false + startOrStopCalculateRouteInfo(false) + return + } + } + + }) + } + } + + private fun updateLocalOrder(){ + routesResult = null + mNextStationIndex = 0 + isGoingToNextStation = false + startOrStopCalculateRouteInfo(false) + mDrivingInfoCallback?.showNoTaskView(true) + } + + private fun updatePassengerRouteInfo(result: PM2RoutesResult) { + mDrivingInfoCallback?.updateLine(result.name, result.runningDur) + if (result.sites != null) { + mDrivingInfoCallback?.showNoTaskView(false) + val stations: List = result.sites + mStations.clear() + mStations.addAll(stations) + mDrivingInfoCallback?.updateLineStations(mStations) + for (i in stations.indices) { + val station: PM2Station = stations[i] + if (station.drivingStatus == BusPassengerConst.STATION_STATUS_STOPPED + && station.isLeaving && i + 1 < stations.size) { + mDrivingInfoCallback?.updateStationsInfo(stations as MutableList, i + 1, false) + if (mNextStationIndex != i + 1) { + d(SceneConstant.M_BUS_P+TAG,"och-rotting--start ") + mTwoStationsRouts.clear() + startRemainRouteInfo() + } + isGoingToNextStation = true + mNextStationIndex = i + 1 + return + } else if (station.drivingStatus == BusPassengerConst.STATION_STATUS_STOPPED && !station.isLeaving) { + mPreRouteIndex = 0 + isGoingToNextStation = false + startOrStopCalculateRouteInfo(false) + mDrivingInfoCallback?.updateStationsInfo(stations as MutableList, i, true) + return + } + } + } + + } + + fun loopRouteAndWipe(){ + if (mRoutePoints != null && mRoutePoints.size > 0 && mLocation != null) { + val haveArrivedIndex = CoordinateCalculateRouteUtil + .getArrivedPointIndexNew( + mWipePreIndex, + mRoutePoints, + mLocation + ) + mWipePreIndex = haveArrivedIndex + d(SceneConstant.M_BUS_P + TAG, + "thread = " + Thread.currentThread().name + " haveArrivedIndex== " + haveArrivedIndex + ) +// if (mAutopilotPlanningCallback != null) { +// val routePoints = CoordinateCalculateRouteUtil +// .coordinateConverterLocationToLatLng(mContext, mRoutePoints) +// mAutopilotPlanningCallback.routeResult(routePoints, haveArrivedIndex) +// } + } + } + + private fun startRemainRouteInfo() { + //开启实时计算剩余距离,剩余时间,预计时间 + startOrStopCalculateRouteInfo(true) + } + + fun dynamicCalculateRouteInfo(){ + //计算当前位置和下一站的剩余点集合 + //计算剩余点总里程和时间 + + //计算当前位置和下一站的剩余点集合 + //计算剩余点总里程和时间 + if (mTwoStationsRouts.size == 0) { + calculateTwoStationsRoute() + } + + if (mTwoStationsRouts.size > 0 && mLocation != null) { + val lastPointsMap = CoordinateCalculateRouteUtil + .getRemainPointListByCompareNew(mPreRouteIndex, mTwoStationsRouts, mLocation) + for (index in lastPointsMap.keys) { + mPreRouteIndex = index + break + } + for (lastPoints in lastPointsMap.values) { + d(SceneConstant.M_BUS_P + TAG, "och-rotting==lastPoints.size() = " + lastPoints.size) + var lastSumLength = 0f + lastSumLength = if (lastPoints.size == 1) { //只是最后一个点,计算当前位置和最后一个点的距离 + if (mNextStationIndex <= mStations.size - 1 && mNextStationIndex >= 0) { + val stationNext: PM2Station = mStations[mNextStationIndex] + CoordinateUtils.calculateLineDistance( + stationNext.gcjLon, stationNext.gcjLat, + mLocation!!.longitude, mLocation!!.latitude + ) + } else { + CoordinateUtils.calculateLineDistance( + lastPoints[0].longitude, lastPoints[0].latitude, + mLocation!!.longitude, mLocation!!.latitude + ) + } + } else { + CoordinateCalculateRouteUtil.calculateRouteSumLength(lastPoints) + } + val lastTime = lastSumLength / BusPassengerConst.SHUTTLE_AVERAGE_SPEED * 3.6 //秒 + d(SceneConstant.M_BUS_P + TAG, "och-rotting==lastSumLength = $lastSumLength") + mDrivingInfoCallback?.updateRemainMT( + lastSumLength.toLong(), + lastTime.toLong() + ) + } + } + } + + private fun calculateTwoStationsRoute() { + //找出前往站对应的轨迹点,拿出两站点的集合 + d(SceneConstant.M_BUS_P + TAG, "mRoutePoints.size() = " + mRoutePoints.size) + if (mRoutePoints.size > 0) { + if (mStations.size > 1) { //两个站点及以上要计算两个站点间的轨迹路线 + if (mNextStationIndex <= mStations.size - 1 && mNextStationIndex - 1 >= 0) { + mTwoStationsRouts.clear() + val stationNext: PM2Station = mStations[mNextStationIndex] + val stationCur: PM2Station = mStations[mNextStationIndex - 1] + //当前站在轨迹中对应的点 + val currentRouteIndex = CoordinateCalculateRouteUtil.getArrivedPointIndexNew( + 0, mRoutePoints, stationCur.gcjLon, stationCur.gcjLat + ) + //要前往的站在轨迹中对应的点 + val nextRouteIndex = CoordinateCalculateRouteUtil.getArrivedPointIndexNew( + currentRouteIndex, + mRoutePoints, + stationNext.gcjLon, + stationNext.gcjLat + ) + + d(SceneConstant.M_BUS_P + TAG, "och-rotting==currentRouteIndex = " + currentRouteIndex + + ", nextRouteIndex = " + nextRouteIndex) + + if (currentRouteIndex < nextRouteIndex) { //如果找到的next在起点的轨迹前面,直接舍弃这个轨迹,不显示 + mTwoStationsRouts.addAll( + mRoutePoints.subList( + currentRouteIndex, + nextRouteIndex + 1 + ) + ) + } + } + } + } + } + + /** + * 开始轮询计算剩余里程和时间 + * @param isStart + */ + fun startOrStopCalculateRouteInfo(isStart: Boolean) { + d(SceneConstant.M_BUS_P+TAG, "startOrStopCalculateRouteInfo() $isStart") + if (isStart) { + PM2ModelLoopManager.startCalculateRouteInfoLoop() + } else { + mTwoStationsRouts.clear() + PM2ModelLoopManager.stopCalculateRouteInfLoop() + } + } + + /** + * 实时轨迹擦除 + * @param isStart + */ + private fun startOrStopRouteAndWipe(isStart: Boolean) { + if (isStart) { + PM2ModelLoopManager.startOrStopRouteAndWipe() + } else { + mWipePreIndex = 0 + PM2ModelLoopManager.stopOrStopRouteAndWipe() + } + } + + private fun startOrStopOrderLoop(start: Boolean) { + d(SceneConstant.M_BUS_P + TAG, "startOrStopOrderLoop() $start") + if (start) { + PM2ModelLoopManager.startQueryDriverLineLoop() + } else { + PM2ModelLoopManager.stopQueryDriverLineLoop() + } + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/model/PM2ServiceManager.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/model/PM2ServiceManager.kt new file mode 100644 index 0000000000..f23b75ea3f --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/model/PM2ServiceManager.kt @@ -0,0 +1,77 @@ +package com.mogo.och.bus.passenger.model + +import android.content.Context +import com.mogo.eagle.core.function.call.telematic.CallerTelematicManager.getServerToken +import com.mogo.cloud.passport.MoGoAiCloudClientConfig +import com.mogo.eagle.core.network.MoGoRetrofitFactory +import com.mogo.och.bus.passenger.bean.PM2OperationStatusResponse +import com.mogo.och.bus.passenger.bean.PM2QueryLineRequest +import com.mogo.och.bus.passenger.bean.PM2RoutesResponse +import com.mogo.och.bus.passenger.network.PM2ServiceApi +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.network.OchCommonSubscribeImpl +import com.mogo.och.common.module.biz.network.interceptor.transformTry + +/** + * Created on 2022/3/31 + */ +object PM2ServiceManager { + + private var mBusPassengerServiceApi = + MoGoRetrofitFactory.getInstance(OchCommonConst.getShuttleUrl()).create(PM2ServiceApi::class.java) + + private var driverSnCache = "" + /** + * 获取Bus司机端的sn + * @return + */ + public val driverAppSn: String + get(){ + val serverToken = getServerToken() + if (serverToken != driverSnCache && serverToken.isNotEmpty()) { + driverSnCache = serverToken + } + return driverSnCache + } + + /** + * 查询绑定行驶的小巴车路线 + * @param context + * @param callback + */ + @JvmStatic + fun queryDriverSiteByCoordinate( + context: Context, callback: OchCommonServiceCallback? + ) { + mBusPassengerServiceApi.queryDriverSiteByCoordinate( + MoGoAiCloudClientConfig.getInstance().serviceAppId, + MoGoAiCloudClientConfig.getInstance().token, + PM2QueryLineRequest( + driverAppSn + ) + ).transformTry() + .subscribe(OchCommonSubscribeImpl(context, callback, "queryDriverSiteByCoordinate=sn =$driverAppSn")) + + } + + /** + * 查询司机端出车收车状态,以及车牌号 + * @param context + * @param callback + */ + @JvmStatic + fun queryDriverOperationStatus( + context: Context, + callback: OchCommonServiceCallback? + ) { + mBusPassengerServiceApi.queryDriverOperationStatus( + MoGoAiCloudClientConfig.getInstance().serviceAppId, + MoGoAiCloudClientConfig.getInstance().token, + driverAppSn + ) + .transformTry() + .subscribe(OchCommonSubscribeImpl(context, callback, "queryDriverOperationStatus=sn =$driverAppSn")) + + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/network/PM2ModelLoopManager.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/network/PM2ModelLoopManager.kt new file mode 100644 index 0000000000..b430a966a1 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/network/PM2ModelLoopManager.kt @@ -0,0 +1,127 @@ +package com.mogo.och.bus.passenger.network + +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.i +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.och.bus.passenger.constant.BusPassengerConst +import com.mogo.och.bus.passenger.model.PM2DrivingModel +import io.reactivex.Observable +import io.reactivex.ObservableOnSubscribe +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.disposables.Disposable +import io.reactivex.schedulers.Schedulers +import java.util.concurrent.TimeUnit + +/** + * @author: wangmingjun + * @date: 2023/2/1 + */ +object PM2ModelLoopManager { + + private val TAG: String = PM2ModelLoopManager::class.java.getSimpleName() + + private var mQueryLineDisposable: Disposable? = null //心跳轮询 + private var mRouteWipeDisposable: CompositeDisposable? = null //估计擦除 + private var mCalculateRouteDisposable: CompositeDisposable? = null //每隔2s计算一次剩余里程和时间 + + + fun startOrStopRouteAndWipe() { + i(SceneConstant.M_BUS_P + TAG, "startOrStopRouteWipe()") + if (mRouteWipeDisposable != null) return + if (mRouteWipeDisposable == null) { + mRouteWipeDisposable = CompositeDisposable() + } + val disposable = startLoopRouteAndWipe() + .doOnSubscribe { } + .doOnError { } + .delay( + BusPassengerConst.LOOP_LINE_1S, + TimeUnit.MILLISECONDS, + true + ) // 设置delayError为true,表示出现错误的时候也需要延迟5s进行通知,达到无论是请求正常还是请求失败,都是5s后重新订阅,即重新请求。 + .subscribeOn(Schedulers.io()) + .repeat() // repeat保证请求成功后能够重新订阅。 + .retry() // retry保证请求失败后能重新订阅 + .observeOn(AndroidSchedulers.mainThread()) + .subscribe { } + mRouteWipeDisposable!!.add(disposable) + } + + fun stopOrStopRouteAndWipe() { + if (mRouteWipeDisposable != null) { + mRouteWipeDisposable!!.dispose() + mRouteWipeDisposable = null + } + } + + fun startQueryDriverLineLoop() { + if (mQueryLineDisposable != null && !mQueryLineDisposable!!.isDisposed) { + return + } + i(SceneConstant.M_BUS_P + TAG, "startQueryDriverLineLoop()") + mQueryLineDisposable = Observable.interval( + BusPassengerConst.LOOP_DELAY, + BusPassengerConst.LOOP_LINE_2S, TimeUnit.MILLISECONDS + ) + .map { aLong: Long -> aLong + 1 } + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe { aLong: Long? -> + PM2DrivingModel.INSTANCE.queryDriverSiteByCoordinate() + } + } + + fun stopQueryDriverLineLoop() { + if (mQueryLineDisposable != null) { + i(SceneConstant.M_BUS_P + TAG, "stopQueryDriverLineLoop()") + mQueryLineDisposable!!.dispose() + mQueryLineDisposable = null + } + } + + fun startCalculateRouteInfoLoop() { + i(SceneConstant.M_BUS_P + TAG, "startCalculateRouteInfoLoop()") + if (mCalculateRouteDisposable != null) return + if (mCalculateRouteDisposable == null) { + mCalculateRouteDisposable = CompositeDisposable() + } + val disposable = startLoopCalculateRouteInfo() + .doOnSubscribe { } + .doOnError { } + .delay( + BusPassengerConst.LOOP_LINE_2S, + TimeUnit.MILLISECONDS, + true + ) // 设置delayError为true,表示出现错误的时候也需要延迟5s进行通知,达到无论是请求正常还是请求失败,都是5s后重新订阅,即重新请求。 + .subscribeOn(Schedulers.io()) + .repeat() // repeat保证请求成功后能够重新订阅。 + .retry() // retry保证请求失败后能重新订阅 + .observeOn(AndroidSchedulers.mainThread()) + .subscribe { } + mCalculateRouteDisposable!!.add(disposable) + } + + fun stopCalculateRouteInfLoop() { + if (mCalculateRouteDisposable != null) { + i(SceneConstant.M_BUS_P + TAG, "stopCalculateRouteInfLoop()") + mCalculateRouteDisposable!!.dispose() + mCalculateRouteDisposable = null + } + } + + private fun startLoopRouteAndWipe(): Observable { + return Observable.create(ObservableOnSubscribe { emitter -> + if (emitter.isDisposed) return@ObservableOnSubscribe + PM2DrivingModel.INSTANCE.loopRouteAndWipe() + emitter.onComplete() + }) + } + + private fun startLoopCalculateRouteInfo(): Observable { + return Observable.create(ObservableOnSubscribe { emitter -> + if (emitter.isDisposed) return@ObservableOnSubscribe + PM2DrivingModel.INSTANCE.dynamicCalculateRouteInfo() + emitter.onComplete() + }) + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/network/PM2ServiceApi.java b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/network/PM2ServiceApi.java new file mode 100644 index 0000000000..9a0f63e23e --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/network/PM2ServiceApi.java @@ -0,0 +1,40 @@ +package com.mogo.och.bus.passenger.network; + +import com.mogo.och.bus.passenger.bean.PM2OperationStatusResponse; +import com.mogo.och.bus.passenger.bean.PM2QueryLineRequest; +import com.mogo.och.bus.passenger.bean.PM2RoutesResponse; + +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; + +/** + * Created on 2022/3/31 + * + * Bus乘客端接口定义 + */ +public interface PM2ServiceApi { + /** + * 查询bus司机端绑定路线 + * @return 接口返回数据 + */ + @Headers( {"Content-Type:application/json;charset=UTF-8"} ) + @POST( "/och-shuttle-cabin/api/business/v1/passenger/lineDataWithDriver/query" ) + Observable queryDriverSiteByCoordinate(@Header("appId") String appId, @Header("ticket") String ticket, @Body PM2QueryLineRequest request); + + /** + * 查询司机端的登陆状态 + * @param sn + * @return + */ + @Headers({"Content-type:application/json;charset=UTF-8"}) +// @GET("/autopilot-car-hailing/car/v2/driver/bus/passenger/takeOrderStatus/query") + @GET("/och-shuttle-cabin/api/business/v1/passenger/loginStatus") + Observable queryDriverOperationStatus(@Header ("appId") String appId, @Header("ticket") String ticket, @Query("sn") String sn); + + +} diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/presenter/PM2ADASPresenter.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/presenter/PM2ADASPresenter.kt new file mode 100644 index 0000000000..de47518d3b --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/presenter/PM2ADASPresenter.kt @@ -0,0 +1,41 @@ +package com.mogo.och.bus.passenger.presenter + +import androidx.lifecycle.LifecycleOwner +import com.mogo.commons.mvp.Presenter +import com.mogo.och.bus.passenger.callback.ADASCallback +import com.mogo.och.bus.passenger.constant.M2Const.Companion.M2_MAP_STATION_MAKER +import com.mogo.och.bus.passenger.model.PM2ADASModel +import com.mogo.och.bus.passenger.ui.PM2HPMapFragment + +class PM2ADASPresenter(view: PM2HPMapFragment?) : + Presenter(view), ADASCallback { + + init { + PM2ADASModel.INSTANCE.init(context) + initListener() + } + + private fun initListener() { + PM2ADASModel.INSTANCE.setAdasCallback(this) + } + + private fun removeListener() { + PM2ADASModel.INSTANCE.setAdasCallback(null) + } + + override fun onDestroy(owner: LifecycleOwner) { + super.onDestroy(owner) + removeListener() + } + + override fun updateHDMapStations(stations: MutableList>) { + for (i in stations.indices){ + mView?.setMapMaker(M2_MAP_STATION_MAKER,stations[i]) + } + + } + + override fun removeHDMapStations() { + mView?.removeMapMaker(M2_MAP_STATION_MAKER) + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/presenter/PM2DrivingPresenter.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/presenter/PM2DrivingPresenter.kt new file mode 100644 index 0000000000..b1cba39ddd --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/presenter/PM2DrivingPresenter.kt @@ -0,0 +1,105 @@ +package com.mogo.och.bus.passenger.presenter + +import androidx.lifecycle.LifecycleOwner +import com.mogo.commons.mvp.Presenter +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.ThreadUtils +import com.mogo.och.bus.passenger.bean.PM2Station +import com.mogo.och.bus.passenger.callback.AutoPilotStatusCallback +import com.mogo.och.bus.passenger.callback.DrivingInfoCallback +import com.mogo.och.bus.passenger.model.PM2ADASModel +import com.mogo.och.bus.passenger.model.PM2DrivingModel +import com.mogo.och.bus.passenger.ui.PM2DrivingInfoFragment + +class PM2DrivingPresenter(view: PM2DrivingInfoFragment?) : + Presenter(view), DrivingInfoCallback, AutoPilotStatusCallback { + + init { + PM2DrivingModel.INSTANCE.init(context) + PM2ADASModel.INSTANCE.init(context) + initListener() + } + + override fun onDestroy(owner: LifecycleOwner) { + super.onDestroy(owner) + destroyListener() + PM2DrivingModel.INSTANCE.releaseListener() + } + + private fun initListener(){ + PM2DrivingModel.INSTANCE.setDrivingInfoCallback(this) + PM2DrivingModel.INSTANCE.setAutoStatusCallback(this) + } + + private fun destroyListener(){ + PM2DrivingModel.INSTANCE.setDrivingInfoCallback(null) + PM2DrivingModel.INSTANCE.setAutoStatusCallback(null) + } + + override fun updateSpeed(speed: Int) { +// CallerLogger.d( +// SceneConstant.M_BUS_P + "speed = ",speed.toString() +// ) + ThreadUtils.runOnUiThread { + mView?.updateSpeed(speed) + } + } + + override fun updatePlateNumber(carNum: String) { + ThreadUtils.runOnUiThread { + mView?.updateCarPlateNum(carNum) + } + } + + override fun updateLine(lineName: String, lineDuring: String) { + ThreadUtils.runOnUiThread { + mView?.updateTaskName(lineName) + mView?.updateTaskDuringTime(lineDuring) + } + } + + override fun updateRemainMT(meters: Long, timeInSecond: Long) { + ThreadUtils.runOnUiThread { + mView?.updateRemainMT(meters, timeInSecond) //米,秒 + } + } + + override fun changeOperationStatus(loginStatus: Boolean) { + ThreadUtils.runOnUiThread { + mView?.changeOperationStatus(loginStatus) + } + } + + override fun showNoTaskView(isTrue: Boolean) { + ThreadUtils.runOnUiThread { + mView?.showNoTaskView(!isTrue) + } + if (isTrue){ + PM2ADASModel.INSTANCE.removeHDMapStations() + } + } + + override fun updateLineStations(stations: MutableList) { + ThreadUtils.runOnUiThread { + mView?.updateLineStations(stations) + } + PM2ADASModel.INSTANCE.updateHDMapStations(stations) + } + + override fun updateStationsInfo(stations: MutableList, i: Int, isArrived: Boolean) { + ThreadUtils.runOnUiThread { + mView?.updateStationsInfo(stations,i,isArrived) + } + } + + override fun updateAutoStatus(isOpen: Boolean) { + ThreadUtils.runOnUiThread { + mView?.updateAutoStatus(isOpen) + } + } + + override fun updateAutoStatus(status: Int) { + + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/presenter/PM2Presenter.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/presenter/PM2Presenter.kt new file mode 100644 index 0000000000..e55cc469d1 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/presenter/PM2Presenter.kt @@ -0,0 +1,7 @@ +package com.mogo.och.bus.passenger.presenter + +import com.mogo.commons.mvp.Presenter +import com.mogo.och.bus.passenger.ui.PM2BaseFragment + +class PM2Presenter(view: PM2BaseFragment?) : + Presenter(view) \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/presenter/PM2VideoPresenter.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/presenter/PM2VideoPresenter.kt new file mode 100644 index 0000000000..b62879bf4b --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/presenter/PM2VideoPresenter.kt @@ -0,0 +1,7 @@ +package com.mogo.och.bus.passenger.presenter + +import com.mogo.commons.mvp.Presenter +import com.mogo.och.bus.passenger.ui.video.PM2VideoFragment + +class PM2VideoPresenter(view: PM2VideoFragment?) : + Presenter(view) \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/provider/M2StatusViewManager.java b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/provider/M2StatusViewManager.java new file mode 100644 index 0000000000..8966090d91 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/provider/M2StatusViewManager.java @@ -0,0 +1,33 @@ +package com.mogo.och.bus.passenger.provider; + +import android.content.Context; +import android.view.View; + +import com.mogo.och.bus.passenger.ui.widget.M2StatusBarView; +import androidx.annotation.NonNull; + +import com.alibaba.android.arouter.facade.annotation.Route; +import com.mogo.eagle.core.data.constants.MogoServicePaths; +import com.mogo.eagle.core.function.api.hmi.view.IStatusViewLayout; + +/** + * @author congtaowang + * @since 2020-01-06 + *

+ * 根据优先级控制显示 window view. + */ +@Route( path = MogoServicePaths.PATH_STATUS_VIEW_MANAGER ) +public class M2StatusViewManager implements IStatusViewLayout { + + + @NonNull + @Override + public View getStatusView(Context context) { + return new M2StatusBarView(context); + } + + @Override + public void init(Context context) { + + } +} diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/PM2BaseFragment.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/PM2BaseFragment.kt new file mode 100644 index 0000000000..a90221bd15 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/PM2BaseFragment.kt @@ -0,0 +1,72 @@ +package com.mogo.och.bus.passenger.ui + +import android.provider.Settings +import android.view.Surface +import com.mogo.commons.mvp.MvpFragment +import com.mogo.och.bus.passenger.R +import com.mogo.och.bus.passenger.presenter.PM2Presenter +import com.mogo.och.bus.passenger.ui.video.PM2VideoFragment + +/** + * @author: wangmingjun + * @date: 2022/4/12 + */ +class PM2BaseFragment : + MvpFragment() { + + private var drivingFragment : PM2DrivingInfoFragment? = null + private var hdMapFragment : PM2HPMapFragment? = null + private var videoFragment : PM2VideoFragment? = null + + override fun getLayoutId(): Int { + return R.layout.p_m2_fragment + } + + override fun getTagName(): String { + return TAG + } + + override fun initViews() { + //横竖屏 +// setScreenDirection() + + //隐藏小地图 + initFragment() + } + +// private fun setScreenDirection() { +// var ro = Settings.System.getInt(context?.contentResolver, +// Settings.System.USER_ROTATION,Surface.ROTATION_270) +// if (ro != Surface.ROTATION_270){ +// ro = Surface.ROTATION_270 +// } +// Settings.System.putInt(context?.contentResolver, +// Settings.System.USER_ROTATION,ro) +// } + + /** + * 初始化行程信息,高静地图,宣传 三个fragment + */ + private fun initFragment() { + + if (drivingFragment == null) drivingFragment = PM2DrivingInfoFragment() + childFragmentManager.beginTransaction().add(R.id.driving_fragment, drivingFragment!!) + .show(drivingFragment!!).commitAllowingStateLoss() + + if (hdMapFragment == null) hdMapFragment = PM2HPMapFragment() + childFragmentManager.beginTransaction().add(R.id.hd_map_fragment, hdMapFragment!!) + .show(hdMapFragment!!).commitAllowingStateLoss() + + if (videoFragment == null) videoFragment = PM2VideoFragment() + childFragmentManager.beginTransaction().add(R.id.video_fragment, videoFragment!!) + .show(videoFragment!!).commitAllowingStateLoss() + } + + override fun createPresenter(): PM2Presenter { + return PM2Presenter(this) + } + + companion object { + private val TAG = PM2BaseFragment::class.java.simpleName + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/PM2DrivingInfoFragment.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/PM2DrivingInfoFragment.kt new file mode 100644 index 0000000000..a9abc4ee54 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/PM2DrivingInfoFragment.kt @@ -0,0 +1,253 @@ +package com.mogo.och.bus.passenger.ui + +import android.graphics.BitmapFactory +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.view.View +import androidx.core.content.ContextCompat +import com.amap.api.maps.model.LatLng +import com.mogo.commons.mvp.MvpFragment +import com.mogo.eagle.core.function.hmi.ui.setting.ToggleDebugView +import com.mogo.eagle.core.utilcode.kotlin.onClick +import com.mogo.eagle.core.utilcode.util.DateTimeUtils +import com.mogo.eagle.core.utilcode.util.UiThreadHandler +import com.mogo.och.bus.passenger.R +import com.mogo.och.bus.passenger.bean.PM2Station +import com.mogo.och.bus.passenger.presenter.PM2DrivingPresenter +import com.mogo.och.common.module.utils.DateTimeUtil.* +import com.mogo.och.common.module.utils.NumberFormatUtil +import kotlinx.android.synthetic.m2.p_m2_driving_info_fragment.* +import java.lang.ref.WeakReference +import kotlin.math.ceil +import kotlin.math.roundToInt + +/** + * @author: wangmingjun + * @date: 2022/4/12 + */ +class PM2DrivingInfoFragment : + MvpFragment() { + +// private var timeHandler: TimeHandler? = null + + /** + * 改变自动驾驶状态 + * + * @param status 2 - running 1 - enable 2 - disable + */ + override fun getLayoutId(): Int { + return R.layout.p_m2_driving_info_fragment + } + + override fun getTagName(): String { + return TAG + } + + override fun initViews() { + speed_tv.setOnLongClickListener { + context?.let { ToggleDebugView.toggleDebugView.toggle(it) } + true + } + + line_name_tv.setTextColor(resources.getColor(R.color.m2_line_name_tv_color)) + station_name_tv.setTextColor(resources.getColor(R.color.m2_line_name_tv_color)) + +// current_time_tv.onClick { + +// //测试V2X消息 +// CallerMsgBoxManager.saveMsgBox( +// MsgBoxBean( +// MsgBoxType.V2X, +// V2XMsg( +// "6666", +// "超速行驶", +// "" +// ) +// ) +// ) +// +// val noticeTrafficStylePushData = NoticeTrafficStylePushData() +// noticeTrafficStylePushData.content= "测试公告布局" +// val noticeFromCloudMsg = NoticeFrCloudMsg(null, noticeTrafficStylePushData, 1) +// CallerMsgBoxManager.saveMsgBox( +// MsgBoxBean( +// MsgBoxType.NOTICE, noticeFromCloudMsg) +// ) +// BPRouteDataTestUtils.converToRouteData() +// } + updateCurrentTime() + } + + override fun initViews(savedInstanceState: Bundle?) { + super.initViews(savedInstanceState) + overMapView?.let { + it.onCreateView(savedInstanceState) + } + } + + override fun onResume() { + super.onResume() + overMapView?.let{ + it.onResume() + } + } + + override fun onPause() { + super.onPause() + overMapView?.let{ + it.onPause() + } + } + + override fun onDestroy() { +// timeHandler?.removeCallbacksAndMessages(null) + super.onDestroy() + overMapView?.let{ + it.onDestroy() + } + } + + fun updateSpeed(speed: Int){ + speed_tv.text = speed.toString() + } + + fun updateCarPlateNum(plateNum : String){ + + } + + fun updateTaskName(name: String){ + line_name_tv.text = name + } + + fun updateTaskDuringTime(time : String){ + line_during_tv.text = time + } + + private fun updateCurrentTime(){ + current_time_tv.text = formatCalendarToString( + DateTimeUtils.getCurrentDateTime(),HH_mm) + + val date = formatCalendarToString( + DateTimeUtils.getCurrentDateTime(), yy_MM_dd) + val weekDay = DateTimeUtils.getWeekDayFromCalendar1(DateTimeUtils.getCurrentDateTime()) + "$date $weekDay".also { current_weekday_tv.text = it } + + sendUpdateTimeTask() // 每10s更新一次 + } + + fun changeOperationStatus(status:Boolean){ + if (!status){ + updateNoOrderUI() + } + } + + fun showNoTaskView(haveTask: Boolean){ + setLineInfoView(haveTask) + } + + private fun setLineInfoView(isShow: Boolean){ + if (isShow){ + line_name_tv.visibility = View.VISIBLE + line_during_tv.visibility = View.VISIBLE + no_line_tv.visibility = View.GONE + }else{ + updateNoOrderUI() + } + } + + private fun updateNoOrderUI() { + line_name_tv.visibility = View.GONE + line_during_tv.visibility = View.GONE + no_line_tv.visibility = View.VISIBLE + updateNoStationView() + overMapView?.let { + it.clearSiteMarkers() + } + overMapView?.let { + it.clearCustomPolyline() + } + } + + private fun updateNoStationView(){ + station_name_tv.setTextColor(resources.getColor(R.color.m2_next_tv_color)) + station_name_title_tv.text = resources.getString(R.string.m2_p_station_title_tv) + station_name_tv.text = resources.getString(R.string.m2_p_empty_tv) + remain_mt.text = resources.getString(R.string.m2_p_empty_remain_km_minute) + } + + override fun createPresenter(): PM2DrivingPresenter { + return PM2DrivingPresenter(this) + } + + fun updateAutoStatus(isAutoPilot: Boolean) { + if (isAutoPilot){ + context?.let { auto_tv.setTextColor(ContextCompat.getColor(it,R.color.m2_p_white_color)) } + context?.let { auto_tv.background = ContextCompat.getDrawable(it,R.drawable.auto_button_bg) } + }else{ + context?.let { auto_tv.setTextColor(ContextCompat.getColor(it,R.color.m2_button_auto_tv_color)) } + context?.let { auto_tv.background = ContextCompat.getDrawable(it,R.drawable.bg_p_m2_auto) } + } + } + + fun updateLineStations(stations: MutableList){ + var stationsList = mutableListOf() + for (i in stations.indices){ + val station = stations[i] + var latLng = LatLng(station.gcjLat,station.gcjLon) + stationsList.add(latLng) + } + overMapView?.let { + it.drawSiteMarkers(stationsList, + BitmapFactory.decodeResource(resources,R.drawable.m2_map_staton_icon),0.5f,0.9f) + } + } + + fun updateStationsInfo(stations: MutableList, i: Int, isArrived: Boolean){ + if (stations.size == 0) return + if (0<= i && i 0) { + if (meters / 1000 < 1) { + disUnit = "米" + remainDis = meters.toFloat().roundToInt().toString() + } else { + disUnit = "公里" + remainDis = NumberFormatUtil.formatLong(meters.toDouble() / 1000) + } + } + + val time = ceil(timeInSecond / 60f).toInt() + + "$remainDis$disUnit | $time 分钟".also { remain_mt.text = it } + } + + private fun sendUpdateTimeTask() { + UiThreadHandler.postDelayed({ + updateCurrentTime() + },LOOP_TIME_TEXT) + } + + companion object { + private val TAG = PM2DrivingInfoFragment::class.java.simpleName + const val LOOP_TIME_TEXT = 10 * 1000L + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/PM2HPMapFragment.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/PM2HPMapFragment.kt new file mode 100644 index 0000000000..05b1101cfd --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/PM2HPMapFragment.kt @@ -0,0 +1,122 @@ +package com.mogo.och.bus.passenger.ui + +import android.os.Bundle +import com.mogo.commons.AbsMogoApplication +import com.mogo.commons.mvp.MvpFragment +import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager.getMapUIController +import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager.getMarkerManager +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d +import com.mogo.map.marker.MogoMarkerOptions +import com.mogo.och.bus.passenger.R +import com.mogo.och.bus.passenger.constant.M2Const.Companion.TYPE_MARKER_M2_LINE +import com.mogo.och.bus.passenger.presenter.PM2ADASPresenter +import com.mogo.och.common.module.utils.OCHThreadPoolManager +import kotlinx.android.synthetic.m2.p_m2_hpmap_fragment.* +import java.util.* + +/** + * @author: wangmingjun + * @date: 2022/4/12 + */ +class PM2HPMapFragment : + MvpFragment() { + /** + * 改变自动驾驶状态 + * + * @param status 2 - running 1 - enable 2 - disable + */ + override fun getLayoutId(): Int { + return R.layout.p_m2_hpmap_fragment + } + + override fun getTagName(): String { + return TAG + } + + override fun initViews() { + } + + override fun initViews(savedInstanceState: Bundle?) { + super.initViews(savedInstanceState) + mapBizView.onCreate(savedInstanceState) + } + + override fun onResume() { + super.onResume() + mapBizView.onResume() + } + + override fun onLowMemory() { + super.onLowMemory() + mapBizView.onLowMemory() + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + mapBizView.onSaveInstanceState(outState) + } + + override fun onPause() { + super.onPause() + mapBizView.onPause() + } + + override fun onDestroyView() { + mapBizView.onDestroy() + super.onDestroyView() + } + + override fun createPresenter(): PM2ADASPresenter { + return PM2ADASPresenter(this) + } + + companion object { + private val TAG = PM2HPMapFragment::class.java.simpleName + } + + fun setMapMaker( + uuid: String, + station: MutableList, + ) { + //开启线程执行起终点marker设置 + val setMapMarkerRunnable = Runnable { + d("setMapMaker= " + Thread.currentThread().name, + uuid + "=latitude=" + station[1] + ",longitude=" + station[0]) + val options = MogoMarkerOptions() + .owner(TYPE_MARKER_M2_LINE) + .anchor(0.5f, 0.5f) + .set3DMode(true) + .gps(true) + .controlAngle(true) + .icon3DRes(R.raw.star_marker) + .longitude(station[0]) + .latitude(station[1]) + val marker = Objects.requireNonNull( + getMarkerManager(AbsMogoApplication.getApp()) + )?.addMarker(uuid, options) + val centerLine = + getMapUIController()!! + .getCenterLineInfo( + station[0], station[1], -1f + ) + if (null != centerLine && marker != null) { // 有可能鹰眼map为空没有角度。判空使用后可能造成maker角度跟道路角度不一致 + marker.setRotateAngle(centerLine.angle!!.toFloat()) + } + } + OCHThreadPoolManager.getsInstance().execute(setMapMarkerRunnable) + } + + fun removeMapMaker( + uuid: String, + ) { + //开启线程移除起终点marker设置 + val removeMapMarkerRunnable = Runnable { + d("RemoveMapMaker=" + Thread.currentThread().name, uuid) + Objects.requireNonNull( + getMarkerManager(AbsMogoApplication.getApp()) + )?.removeMarkers(uuid) + } + OCHThreadPoolManager.getsInstance().execute(removeMapMarkerRunnable) + } + +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/video/PM2VideoFragment.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/video/PM2VideoFragment.kt new file mode 100644 index 0000000000..6eee9039d4 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/video/PM2VideoFragment.kt @@ -0,0 +1,234 @@ +package com.mogo.och.bus.passenger.ui.video + +import com.mogo.commons.mvp.MvpFragment +import com.mogo.och.bus.passenger.R +import com.mogo.och.bus.passenger.presenter.PM2VideoPresenter +import com.mogo.och.bus.passenger.ui.widget.video.RotationItem +import kotlinx.android.synthetic.m2.p_m2_video_fragment.* + +/** + * @author: wangmingjun + * @date: 2022/4/12 + */ +class PM2VideoFragment : + MvpFragment() { + + private var arrayListOf = mutableListOf() + + override fun getLayoutId(): Int { + return R.layout.p_m2_video_fragment + } + + + override fun createPresenter(): PM2VideoPresenter { + return PM2VideoPresenter(this) + } + + companion object { + private val TAG = PM2VideoFragment::class.java.simpleName + } + + override fun getTagName(): String { + return TAG + } + + override fun initViews() { + initResourceData() + imageVideoRotationView.setData(arrayListOf) + } + + override fun onPause() { + super.onPause() + imageVideoRotationView.setPause() + } + + override fun onResume() { + super.onResume() + imageVideoRotationView.setResume() + } + + private fun initResourceData() { + arrayListOf.clear() + arrayListOf.add( + RotationItem( + "https://img.zhidaohulian.com/fileServer/online_car_hailing/1678946244305/dalim2.mp4", + 1, + "", + "1" + ) + ) +// if (BuildConfig.FLAVOR.contains("dali")){ //大理 目前还都使用的mogo 的cos https://img.zhidaohulian.com/fileServer/online_car_hailing/1678932482045/1080%2A565%20.mp4 +// arrayListOf.add( +// RotationItem( +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1678932482045/1080%2A565%20.mp4", +// 1, +// "", +// "1" +// ) +// ) +// }else if (BuildConfig.FLAVOR.contains("yantai")){ //烟台 +// arrayListOf.add( +// RotationItem( +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676357256102/1.jpg", +// 0, +// "", +// "1" +// ) +// ) +// arrayListOf.add( +// RotationItem( +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676357382357/2.png", +// 0, +// "", +// "2" +// ) +// ) +// arrayListOf.add( +// RotationItem( +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676357557335/3.mp4", +// 1, +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676357382357/2.png", +// "3" +// ) +// ) +// arrayListOf.add( +// RotationItem( +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676357598483/4.jpg", +// 0, +// "", +// "4" +// ) +// ) +// arrayListOf.add( +// RotationItem( +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676357834634/5.m4v", +// 1, +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676357598483/4.jpg", +// "5" +// ) +// ) +// arrayListOf.add( +// RotationItem( +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676358660379/6.m4v", +// 1, +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676357598483/4.jpg", +// "6" +// ) +// ) +// arrayListOf.add( +// RotationItem( +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676360154589/7.jpg", +// 0, +// "", +// "7" +// ) +// ) +// arrayListOf.add( +// RotationItem( +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676360185500/8.jpg", +// 0, +// "", +// "8" +// ) +// ) +// arrayListOf.add( +// RotationItem( +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676360224773/9.png", +// 0, +// "", +// "9" +// ) +// ) +// arrayListOf.add( +// RotationItem( +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676360274126/10.mp4", +// 1, +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676360224773/9.png", +// "10" +// ) +// ) +// }else{ // mogo +// arrayListOf.add( +// RotationItem( +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676357256102/1.jpg", +// 0, +// "", +// "1" +// ) +// ) +// arrayListOf.add( +// RotationItem( +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676357382357/2.png", +// 0, +// "", +// "2" +// ) +// ) +// arrayListOf.add( +// RotationItem( +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676357557335/3.mp4", +// 1, +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676357382357/2.png", +// "3" +// ) +// ) +// arrayListOf.add( +// RotationItem( +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676357598483/4.jpg", +// 0, +// "", +// "4" +// ) +// ) +// arrayListOf.add( +// RotationItem( +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676357834634/5.m4v", +// 1, +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676357598483/4.jpg", +// "5" +// ) +// ) +// arrayListOf.add( +// RotationItem( +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676358660379/6.m4v", +// 1, +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676357598483/4.jpg", +// "6" +// ) +// ) +// arrayListOf.add( +// RotationItem( +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676360154589/7.jpg", +// 0, +// "", +// "7" +// ) +// ) +// arrayListOf.add( +// RotationItem( +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676360185500/8.jpg", +// 0, +// "", +// "8" +// ) +// ) +// arrayListOf.add( +// RotationItem( +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676360224773/9.png", +// 0, +// "", +// "9" +// ) +// ) +// arrayListOf.add( +// RotationItem( +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676360274126/10.mp4", +// 1, +// "https://img.zhidaohulian.com/fileServer/online_car_hailing/1676360224773/9.png", +// "10" +// ) +// ) +// } +// + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/M2BlueToothView.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/M2BlueToothView.kt new file mode 100644 index 0000000000..f11882f70d --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/M2BlueToothView.kt @@ -0,0 +1,37 @@ +package com.mogo.och.bus.passenger.ui.widget + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import com.mogo.eagle.core.function.api.devatools.IMoGoDevaToolsListener +import com.mogo.eagle.core.function.hmi.ui.widget.BlueToothView +import com.mogo.eagle.core.utilcode.util.ThreadUtils +import com.mogo.och.bus.passenger.R +import kotlinx.android.synthetic.m2.p_m2_view_blue_tooth.view.* + +/** + * 魔戒蓝牙控件 + * 放置于StatusBar右侧位置 + * todo arrow + */ +class M2BlueToothView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : BlueToothView(context, attrs, defStyleAttr),IMoGoDevaToolsListener { + + init { + LayoutInflater.from(context).inflate(R.layout.p_m2_view_blue_tooth, this, true) + } + + override fun mofangStatus(status: Boolean) { + ThreadUtils.runOnUiThread { + if (status) { + blueView.setImageResource(R.drawable.m2_blue_tooth_close) + } else { + blueView.setImageResource(R.drawable.m2_blue_tooth_open) + } + } + } + +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/M2PTrafficLightView.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/M2PTrafficLightView.kt new file mode 100644 index 0000000000..8560ce030b --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/M2PTrafficLightView.kt @@ -0,0 +1,179 @@ +package com.mogo.och.bus.passenger.ui.widget + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import com.mogo.eagle.core.data.enums.DataSourceType +import com.mogo.eagle.core.data.enums.TrafficLightEnum +import com.mogo.eagle.core.function.api.datacenter.union.IMoGoTrafficLightListener +import com.mogo.eagle.core.function.call.v2x.CallerTrafficLightListenerManager +import com.mogo.eagle.core.utilcode.util.UiThreadHandler +import com.mogo.och.bus.passenger.R +import kotlinx.android.synthetic.m2.m2_p_traffic_light_view.view.* + +/** + * bus乘客端:红绿灯view + * + * Created on 2022/3/14 + */ +class M2PTrafficLightView @JvmOverloads constructor( + context: Context?, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : LinearLayout(context, attrs, defStyleAttr), IMoGoTrafficLightListener { + + companion object { + private const val TAG = "M2PTrafficLightView" + } + + private var mCurrentLightId = TrafficLightEnum.BLACK + + init { + init(context) + } + + private fun init(context: Context?) { + LayoutInflater.from(context).inflate(R.layout.m2_p_traffic_light_view, this, true) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + CallerTrafficLightListenerManager.addListener(TAG, this) + } + + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + CallerTrafficLightListenerManager.removeListener(TAG) + } + + /** + * 展示红绿灯预警 + * + * @param checkLightId 0-都是默认,1-红,2-黄,3-绿 + * @param lightSource 1:云端下发;2:自车感知 + */ + override fun showTrafficLight(checkLightId: TrafficLightEnum, lightSource: DataSourceType) { + super.showTrafficLight(checkLightId, lightSource) + mCurrentLightId = checkLightId + updateTrafficLightIcon(checkLightId) + } + + /** + * 关闭红绿灯预警展示,并重制灯态 + */ + override fun disableTrafficLight() { + super.disableTrafficLight() + UiThreadHandler.post { + mCurrentLightId = TrafficLightEnum.BLACK + this@M2PTrafficLightView.visibility = GONE + } + } + + /** + * @param redNum 红灯倒计时 + * @param yellowNum 黄灯倒计时 + * @param greenNum 绿灯倒计时 + */ + override fun changeCountdownTrafficLightNum(redNum: Int, yellowNum: Int, greenNum: Int) { + super.changeCountdownTrafficLightNum(redNum, yellowNum, greenNum) + resetView() + when (mCurrentLightId) { + TrafficLightEnum.RED -> changeCountdownRed(redNum) + TrafficLightEnum.YELLOW -> changeCountdownYellow(yellowNum) + TrafficLightEnum.GREEN -> changeCountdownGreen(greenNum) + else -> UiThreadHandler.post { m2_p_traffic_light_time_tv.text = "" } + } + } + + override fun changeCountdownRed(redNum: Int) { + super.changeCountdownRed(redNum) + UiThreadHandler.post { + if (redNum > 0) { + resetView() + m2_p_traffic_light_time_tv.text = redNum.toString() + } else { + disableTrafficLightCountDown() + m2_p_traffic_light_time_tv.text = "" + } + } + } + + override fun changeCountdownGreen(greenNum: Int) { + super.changeCountdownGreen(greenNum) + UiThreadHandler.post { + if (greenNum > 0) { + resetView() + m2_p_traffic_light_time_tv.text = greenNum.toString() + } else { + disableTrafficLightCountDown() + m2_p_traffic_light_time_tv.text = "" + } + } + } + + override fun changeCountdownYellow(yellowNum: Int) { + super.changeCountdownYellow(yellowNum) + UiThreadHandler.post { + if (yellowNum > 0) { + resetView() + m2_p_traffic_light_time_tv.text = yellowNum.toString() + } else { + disableTrafficLightCountDown() + m2_p_traffic_light_time_tv.text = "" + } + } + } + + /** + * 更新红绿灯icon + * + * @param lightId 0-都是默认,1-红,2-黄,3-绿 + */ + private fun updateTrafficLightIcon(lightId: TrafficLightEnum) { + UiThreadHandler.post { + when (lightId) { + TrafficLightEnum.RED -> { + m2_p_traffic_light_iv.setBackgroundResource(R.drawable.m2_light_red_nor) + this@M2PTrafficLightView.visibility = VISIBLE + } + TrafficLightEnum.YELLOW -> { + m2_p_traffic_light_iv.setBackgroundResource(R.drawable.m2_light_yellow_nor) + this@M2PTrafficLightView.visibility = VISIBLE + } + TrafficLightEnum.GREEN -> { + m2_p_traffic_light_iv.setBackgroundResource(R.drawable.m2_light_green_nor) + this@M2PTrafficLightView.visibility = VISIBLE + } + else -> this@M2PTrafficLightView.visibility = GONE + } + } + } + + override fun disableTrafficLightCountDown() { + super.disableTrafficLightCountDown() + UiThreadHandler.post { + val layoutParams = layoutParams + if (layoutParams is MarginLayoutParams) { + val lp = layoutParams + lp.width = resources.getDimension(R.dimen.dp_40).toInt() + setLayoutParams(lp) + m2_p_traffic_light_time_tv.visibility = GONE + m2_p_traffic_light_bg.layoutParams.width = + resources.getDimension(R.dimen.dp_40).toInt() + } + } + } + + private fun resetView() { + val layoutParams = layoutParams + if (layoutParams is MarginLayoutParams) { + val lp = layoutParams + lp.width = resources.getDimension(R.dimen.m2_p_light_width).toInt() + setLayoutParams(lp) + m2_p_traffic_light_time_tv.visibility = VISIBLE + m2_p_traffic_light_bg.layoutParams.width = + resources.getDimension(R.dimen.m2_p_light_width).toInt() + } + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/M2StatusBarView.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/M2StatusBarView.kt new file mode 100644 index 0000000000..932bd2f659 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/M2StatusBarView.kt @@ -0,0 +1,109 @@ +package com.mogo.och.bus.passenger.ui.widget + +import android.annotation.* +import android.content.Context +import android.graphics.Color +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.constraintlayout.widget.ConstraintLayout +import chassis.ChassisStatesOuterClass +import com.mogo.eagle.core.function.api.autopilot.IMoGoBatteryManagementSystemListener +import com.mogo.eagle.core.function.api.hmi.view.IViewControlListener +import com.mogo.eagle.core.function.api.setting.IMoGoSkinModeChangeListener +import com.mogo.eagle.core.function.call.autopilot.CallerBatteryManagementSystemListenerManager +import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager +import com.mogo.eagle.core.function.call.hmi.CallerHmiViewControlListenerManager +import com.mogo.eagle.core.function.call.setting.CallerSkinModeListenerManager +import com.mogo.eagle.core.utilcode.kotlin.* +import com.mogo.eagle.core.utilcode.util.ClickUtils +import com.mogo.och.bus.passenger.R +import kotlinx.android.synthetic.m2.p_m2_view_status_bar.view.* +import kotlinx.coroutines.* +import me.jessyan.autosize.utils.AutoSizeUtils + +/** + * @author: wangmingjun + * @date: 2023/2/14 + */ +class M2StatusBarView @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null +) : ConstraintLayout(context, attrs), IViewControlListener, IMoGoSkinModeChangeListener, + IMoGoBatteryManagementSystemListener { + + companion object { + const val TAG = "M2StatusBarView" + } + + @Volatile + private var oldBmsSoc: Float = -1.0f + + init { + LayoutInflater.from(context).inflate(R.layout.p_m2_view_status_bar, this, true) + setBackgroundColor(Color.parseColor("#80FFFFFF")) + isClickable = true + isFocusable = true + } + + + @SuppressLint("ClickableViewAccessibility") + override fun onAttachedToWindow() { + super.onAttachedToWindow() + post { + val params: ViewGroup.LayoutParams = getLayoutParams() + params.height = AutoSizeUtils.dp2px(context,40f) + layoutParams = params + } + //添加view控制 + CallerHmiViewControlListenerManager.addListener(TAG,this) + // 添加换肤监听 + CallerSkinModeListenerManager.addListener(TAG, this) + //电量 + CallerBatteryManagementSystemListenerManager.addListener(TAG,this) + + progress?.also { + it.progress = 50 + } + tv_power_cos?.also { + it.text = "50%" + } + } + + override fun onSkinModeChange(skinMode: Int) { + when (skinMode) { + 0 -> setStatusBarDarkOrLight(false) + 1 -> setStatusBarDarkOrLight(true) + } + } + + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + CallerHmiViewControlListenerManager.removeListener(TAG) + CallerSkinModeListenerManager.removeListener(TAG) + CallerDevaToolsManager.hideStatusBar() + } + + @SuppressLint("SetTextI18n") + override fun onBatteryManagementSystemStates(states: ChassisStatesOuterClass.BMSSystemStates) { + if (ClickUtils.isClickTooFrequent(this,1000)) { + return + } + val bmsSoc = states.bmsSoc + try { + if (oldBmsSoc != bmsSoc ) { + scope.launch { + if(bmsSoc >1){ + progress?.also { it.progress = bmsSoc.toInt() } + tv_power_cos?.also { it.text = "${bmsSoc.toInt()}%" } + }else{ + val power = (bmsSoc * 100).toInt() + progress?.also { it.progress = power } + tv_power_cos?.also {it.text = "$power%" } + } + } + } + } finally { + oldBmsSoc = bmsSoc + } + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/M2TurnLightView.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/M2TurnLightView.kt new file mode 100644 index 0000000000..17d5780835 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/M2TurnLightView.kt @@ -0,0 +1,16 @@ +package com.mogo.och.bus.passenger.ui.widget + +import android.content.Context +import android.util.AttributeSet +import com.mogo.eagle.core.function.hmi.ui.vehicle.TurnLightViewStatus + +/** + * @author: wangmingjun + * @date: 2023/2/13 + */ +class M2TurnLightView @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null +) : TurnLightViewStatus(context, attrs) { + + +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/video/AdvanceGSYVideoPlayer.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/video/AdvanceGSYVideoPlayer.kt new file mode 100644 index 0000000000..d3244e8f7b --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/video/AdvanceGSYVideoPlayer.kt @@ -0,0 +1,127 @@ +package com.mogo.och.bus.passenger.ui.widget.video + +import android.content.Context +import android.media.AudioManager +import android.util.AttributeSet +import com.mogo.eagle.core.utilcode.mogo.logger.Logger +import com.shuyu.gsyvideoplayer.utils.Debuger +import com.shuyu.gsyvideoplayer.utils.GSYVideoType +import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer + +/** + * @author: wangmingjun + * @date: 2023/2/17 + * 隐藏所有控件的player + */ +class AdvanceGSYVideoPlayer: StandardGSYVideoPlayer { + constructor(context: Context?) : super(context) + constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) + + init { + hideWidget() + GSYVideoType.setShowType(GSYVideoType.SCREEN_MATCH_FULL) + GSYVideoType.setRenderType(GSYVideoType.GLSURFACE) + } + + override fun hideAllWidget() { + Logger.d(ImageAndVideoRotation.TAG, "hideAllWidget") +// hideWidget() + } + + override fun changeUiToNormal() { + Logger.d(ImageAndVideoRotation.TAG, "changeUiToNormal-hide") + hideWidget() + } + + override fun changeUiToPreparingShow() { + Logger.d(ImageAndVideoRotation.TAG, "changeUiToPreparingShow-hide") + hideWidget() + } + + override fun changeUiToPlayingShow() { + Logger.d(ImageAndVideoRotation.TAG, "changeUiToPlayingShow") + setCacheImageViewGone() + } + + override fun changeUiToPauseShow() { + Logger.d(ImageAndVideoRotation.TAG, "changeUiToPauseShow-hide") + startPlayLogic() +// hideWidget() + } + + override fun changeUiToCompleteShow() { + Logger.d(ImageAndVideoRotation.TAG, "changeUiToCompleteShow") + setCacheImageViewGone() + } + + override fun changeUiToPlayingBufferingShow() { + Logger.d(ImageAndVideoRotation.TAG, "changeUiToPlayingBufferingShow -hide") + hideWidget() + } + + override fun changeUiToError() { + Logger.d(ImageAndVideoRotation.TAG, "changeUiToError-hide") + hideWidget() + } + + private fun hideWidget(){ + setViewShowState(mBottomContainer, INVISIBLE) + setViewShowState(mProgressBar, INVISIBLE) + setViewShowState(mCurrentTimeTextView, INVISIBLE) + setViewShowState(mTotalTimeTextView, INVISIBLE) + setViewShowState(mBottomProgressBar, INVISIBLE) + setViewShowState(mBackButton, INVISIBLE) + setViewShowState(mStartButton, INVISIBLE) + + setViewShowState(mThumbImageViewLayout, VISIBLE) + setViewShowState(mThumbImageView, VISIBLE) + + setViewShowState(mTopContainer, INVISIBLE) + + setViewShowState(mLoadingProgressBar, INVISIBLE) + setViewShowState( + mLockScreen, INVISIBLE + ) + + setIsTouchWiget(false) + isFocusableInTouchMode = false + } + + fun setCacheImageViewVisible() { + Logger.d(ImageAndVideoRotation.TAG, "CacheImageViewVISIBLE") + setViewShowState(mThumbImageViewLayout, VISIBLE) +// setViewShowState(mThumbImageView, VISIBLE) + } + + fun setCacheImageViewGone() { + Logger.d(ImageAndVideoRotation.TAG, "CacheImageViewGONE") + setViewShowState(mThumbImageViewLayout, INVISIBLE) +// setViewShowState(mThumbImageView, INVISIBLE) + } + + //失去焦点声音压低 + override fun onLossTransientCanDuck() { +// setStreamVolume(0.2f) + setNeedMute(true) + } + + //获取焦点声音恢复 + override fun onGankAudio() { +// setStreamVolume(5.0f) + setNeedMute(false) + } + + private fun setStreamVolume(percent: Float){ + var mAudioManager = mContext?.getSystemService(Context.AUDIO_SERVICE) as AudioManager + var maxVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC) + var volume = (percent * maxVolume).toInt() + if (volume < 0 ){ + volume = 0 + } + mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC,volume,0) + } + + private fun setNeedMute(isMute: Boolean){ + gsyVideoManager?.player?.setNeedMute(isMute) + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/video/AdvanceImageView.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/video/AdvanceImageView.kt new file mode 100644 index 0000000000..cf0d030989 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/video/AdvanceImageView.kt @@ -0,0 +1,45 @@ +package com.mogo.och.bus.passenger.ui.widget.video + +import android.annotation.SuppressLint +import android.content.Context +import android.util.AttributeSet +import android.widget.ImageView +import android.widget.RelativeLayout +import com.bumptech.glide.Glide +import com.bumptech.glide.request.RequestOptions +import com.mogo.och.bus.passenger.R + +/** + * @author: wangmingjun + * @date: 2023/2/6 + */ +class AdvanceImageView @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null +) : RelativeLayout(context, attrs) { + + private var imageView: ImageView? = null + + init { + initView() + } + + private fun initView() { + imageView = ImageView(context) + imageView?.scaleType = ImageView.ScaleType.FIT_XY + addView(imageView, LayoutParams(-1, -1)) + } + + @SuppressLint("CheckResult") + fun setImagePath(path: String){ + imageView?.setImageResource(R.drawable.m2_p_video_holder) + imageView?.let { Glide.with(context).asBitmap().load(path) + .apply( + RequestOptions().useUnlimitedSourceGeneratorsPool(true) + .placeholder(R.drawable.m2_p_video_holder) + .error(R.drawable.m2_p_video_holder) + .fallback(R.drawable.m2_p_video_holder) + .centerCrop() + ) + .into(it) } + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/video/AdvancePagerAdapter.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/video/AdvancePagerAdapter.kt new file mode 100644 index 0000000000..db42808e75 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/video/AdvancePagerAdapter.kt @@ -0,0 +1,211 @@ +package com.mogo.och.bus.passenger.ui.widget.video + +import android.content.Context +import android.view.View +import android.view.ViewGroup +import androidx.viewpager.widget.PagerAdapter +import androidx.viewpager.widget.ViewPager +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d +import com.mogo.eagle.core.utilcode.mogo.logger.Logger +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant +import com.mogo.eagle.core.utilcode.util.CountDownTimer +import com.mogo.eagle.core.utilcode.util.UiThreadHandler +import com.shuyu.gsyvideoplayer.listener.GSYSampleCallBack + +/** + * @author: wangmingjun + * @date: 2023/2/6 + */ +class AdvancePagerAdapter(context: Context, viewPager: ViewPager) : PagerAdapter(), + ViewPager.OnPageChangeListener { + + private val mContext: Context = context + private val mViewPager: ViewPager = viewPager + + private var dataList = mutableListOf() + private var viewList = mutableListOf() + + private var lastPosition = -1 + + private var current = 0 + private val time = 5000 + private var pause = false + private var countDownTimer: CountDownTimer? = null + + fun setData(list: MutableList) { + if (list.isEmpty()) return + dataList.addAll(list) + + viewList.clear() + + list.forEach { + addView(it) + } + + mViewPager.addOnPageChangeListener(this) + + notifyDataSetChanged() + + mViewPager.currentItem = 0 + + if (viewList.size > 0) { + if (viewList[mViewPager.currentItem] is AdvanceVideoView) {//有人反应第一个是视频不播放这边优化了一下 + Logger.d(ImageAndVideoRotation.TAG, "第一个是视频") + val video = viewList[mViewPager.currentItem] as AdvanceVideoView + video.setVideo(gsySampleCallBack) + + } else if (viewList[mViewPager.currentItem] is AdvanceImageView) { + Logger.d(ImageAndVideoRotation.TAG, "startTimer()_1") + current = 0//换页重新计算时间 + startTimer() + } + } + } + + override fun getCount(): Int { + return dataList.size + } + + override fun isViewFromObject(view: View, `object`: Any): Boolean { + return view === `object` + } + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + container.removeView(viewList[position]) + } + + override fun instantiateItem(container: ViewGroup, position: Int): Any { + val view: View = viewList[position] + container.addView(view) + return view + + } + + override fun getItemPosition(`object`: Any): Int { + return POSITION_NONE + } + + private fun addView(item: RotationItem) { + if (item.type == 1) { // 表示视频 + val videoView = AdvanceVideoView(mContext) + videoView.setVideoPath(item.path,item.cacheImgPath) + viewList.add(videoView) + } else { // 表示图片 + val imageView = AdvanceImageView(mContext) + imageView.setImagePath(item.path) + viewList.add(imageView) + } + } + + fun setPause() { + pause = true + if (viewList.size > 0 && viewList[mViewPager.currentItem] is AdvanceVideoView) { + val videoView = viewList[mViewPager.currentItem] as AdvanceVideoView + videoView.setPause() + } + } + + fun setResume() { + pause = false + if (viewList.size > 0 && viewList[mViewPager.currentItem] is AdvanceVideoView) { + val videoView = viewList[mViewPager.currentItem] as AdvanceVideoView + videoView.setResume() + } + } + + override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) { + } + + override fun onPageSelected(position: Int) { + } + + override fun onPageScrollStateChanged(state: Int) { + // 由于viewpager的预加载机制onPageSelected这里面加载videoview 放的跟玩一样 等操作完成后再播放videoview就香了 很丝滑 + if (state == 0) { //静止,什么都没做 + val currentItem = mViewPager.currentItem + Logger.d(ImageAndVideoRotation.TAG, + "state = $state currentItem = $currentItem lastPosition = $lastPosition") + + if (viewList.size > 1) { //多于1,才会循环跳转 + + if (viewList[mViewPager.currentItem] is AdvanceVideoView) { + + val videoView = (viewList[mViewPager.currentItem] as AdvanceVideoView) + videoView.setCacheImageViewVisible() + videoView.setVideo(gsySampleCallBack) + + } else if (viewList[mViewPager.currentItem] is AdvanceImageView) { + Logger.d(ImageAndVideoRotation.TAG, "startTimer()") + current = 0//换页重新计算时间 + startTimer() + } + lastPosition = mViewPager.currentItem + } + } + } + + private var gsySampleCallBack = object : GSYSampleCallBack() { + + override fun onPrepared(url: String?, vararg objects: Any?) { + Logger.d(ImageAndVideoRotation.TAG, "onPrepared--$url") + } + + override fun onAutoComplete(url: String?, vararg objects: Any?) { + Logger.d(ImageAndVideoRotation.TAG, "onAutoComplete()-$url") + if (viewList[mViewPager.currentItem] is AdvanceVideoView){ + val videoView = (viewList[mViewPager.currentItem] as AdvanceVideoView) + if (viewList.size == 1){ + videoView.startPlay(url) + }else{ + videoView.onVideoReset() + goNextItemView() + } + } + } + + override fun onPlayError(url: String?, vararg objects: Any?) { + super.onPlayError(url, *objects) + Logger.d(ImageAndVideoRotation.TAG, "onPlayError()-$url") + if (viewList[mViewPager.currentItem] is AdvanceVideoView){ + val videoView = (viewList[mViewPager.currentItem] as AdvanceVideoView) + videoView.onVideoReset() +// videoView.setCacheImageViewVisible() + videoView.clearLocalErrorVideo() + goNextItemView() + } + } + } + + private fun startTimer() { + if (countDownTimer != null){ + countDownTimer?.cancel() + countDownTimer = null + } + countDownTimer = object : CountDownTimer(5000,1000){ + override fun onTick(millisUntilFinished: Long) { + d(SceneConstant.M_BUS_P + "startTimer", "倒计时秒 = ${millisUntilFinished/1000}" ) + } + + override fun onFinish() { + d(ImageAndVideoRotation.TAG+ "startTimer", "5s到,跳转") + goNextItemView() + } + + }.start() + } + + /** + * view 跳转 + */ + private fun goNextItemView() { + if (mViewPager.currentItem == viewList.size - 1) {//已经到最后一个 + mViewPager.post { + mViewPager.setCurrentItem(0, true) + } + } else { + mViewPager.post { + mViewPager.setCurrentItem(mViewPager.currentItem + 1, true) + } + } + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/video/AdvanceVideoView.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/video/AdvanceVideoView.kt new file mode 100644 index 0000000000..29a678e59a --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/video/AdvanceVideoView.kt @@ -0,0 +1,248 @@ +package com.mogo.och.bus.passenger.ui.widget.video + +import android.annotation.SuppressLint +import android.content.Context +import android.net.Uri +import android.util.AttributeSet +import android.widget.ImageView +import android.widget.RelativeLayout +import com.mogo.eagle.core.utilcode.breakpoint.bean.ThreadBean +import com.mogo.eagle.core.utilcode.breakpoint.callback.IDownload +import com.mogo.eagle.core.utilcode.breakpoint.utils.DownloadUtils +import com.mogo.eagle.core.utilcode.mogo.logger.Logger +import com.mogo.eagle.core.utilcode.util.FileUtils +import com.mogo.eagle.core.utilcode.util.ThreadUtils +import com.mogo.eagle.core.utilcode.util.UiThreadHandler +import com.mogo.och.bus.passenger.R +import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder +import com.shuyu.gsyvideoplayer.listener.GSYSampleCallBack +import java.io.File + +/** + * @author: wangmingjun + * @date: 2023/2/8 + */ +class AdvanceVideoView @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null +) : RelativeLayout(context, attrs) { + + private var videoRelativeLayout: RelativeLayout? = null + private var cacheImage: ImageView? = null + private var videoViewPlayer: AdvanceGSYVideoPlayer? = null + private var gsyVideoOptionBuilder: GSYVideoOptionBuilder? = null + private var mOnCompletionListener: GSYSampleCallBack? = null + private var downloadVideoName = "" + private var fileNetPath: String? = "" + private var cacheImageUrl: String? = "" + private var mVideoDirPath: String? = "" + + init { + mVideoDirPath = context.filesDir.absolutePath+ File.separator + "video" + File.separator +// mVideoDirPath = Config.downLoadPath + initView() + } + + private fun initView() { + initVideoView() + initCacheImgView() + } + + private fun initCacheImgView() { + cacheImage = ImageView(context) + cacheImage?.scaleType = ImageView.ScaleType.FIT_XY +// addView(cacheImage, LayoutParams(-1, -1)) + } + + private fun initVideoView() { + videoRelativeLayout = RelativeLayout(context) + addView(videoRelativeLayout, LayoutParams(-1, -1)) + + if (videoViewPlayer === null) { + //视频播放控件 + videoViewPlayer = AdvanceGSYVideoPlayer(context) + } + + var layoutParams = LayoutParams(-1, -1) + //设置videoview占满父view播放 + layoutParams.addRule(ALIGN_PARENT_LEFT) + layoutParams.addRule(ALIGN_PARENT_RIGHT) + layoutParams.addRule(ALIGN_PARENT_TOP) + layoutParams.addRule(ALIGN_PARENT_BOTTOM) + + videoRelativeLayout?.addView(videoViewPlayer, layoutParams) + } + + fun setVideoPath(path: String,cacheImageUrl: String) { + // https://img.zhidaohulian.com/fileServer/online_car_hailing/1676357834634/5.m4v + // https://img.zhidaohulian.com/fileServer/online_car_hailing/1676360274126/10.mp4 + this.fileNetPath = path + this.cacheImageUrl = cacheImageUrl + val pathList = path.split("/") + if (pathList.isNotEmpty()){ + this.downloadVideoName = pathList[pathList.size - 1] + } + } + + private fun loadCacheImg() { + // BitmapHelper.getVideoThumbnail(path) /*获取第一帧图* +// OCHThreadPoolManager.getsInstance().execute { +// var bitmap = BitmapHelper.getVideoThumbnail(fileNetPath) + Logger.d(ImageAndVideoRotation.TAG, "setVideoPath") +// ThreadUtils.runOnUiThread { +// Logger.d(ImageAndVideoRotation.TAG, "bitmap加载") + cacheImage?.setImageResource(R.drawable.m2_p_video_holder) +// cacheImage?.let { //暂时去掉加载首帧图,加载视频时,用本地默认图 +// Glide.with(context).asBitmap().load(cacheImageUrl) +// .apply( +// RequestOptions().useUnlimitedSourceGeneratorsPool(true) +// .placeholder(R.drawable.m2_p_video_holder) +// .error(R.drawable.m2_p_video_holder) +// .fallback(R.drawable.m2_p_video_holder) +// .centerCrop() +// ) +// .into(it) +// } + videoViewPlayer?.thumbImageView = cacheImage +// setCacheImageViewVisible() +// } +// } + } + + fun clearLocalErrorVideo(){ + if (downloadVideoName.isNotEmpty() + && FileUtils.isFileExists(mVideoDirPath + downloadVideoName)){ + FileUtils.delete(mVideoDirPath + downloadVideoName) + } + } + + @SuppressLint("CheckResult") + fun setCacheImageViewVisible() { + UiThreadHandler.post { +// cacheImage?.visibility = VISIBLE + videoViewPlayer?.setCacheImageViewVisible() + } + } + + fun setCacheImageViewGone() { + UiThreadHandler.post { +// cacheImage?.visibility = GONE + videoViewPlayer?.setCacheImageViewGone() + } + + } + + fun setVideo(onCompletionListener: GSYSampleCallBack) { + loadCacheImg() + Logger.d(ImageAndVideoRotation.TAG, "setVideo") + mOnCompletionListener = onCompletionListener + //判断是否已经下载 + if (downloadVideoName.isNotEmpty()){ + Logger.d(ImageAndVideoRotation.TAG, + "video local url = $mVideoDirPath$downloadVideoName" + ) + if (FileUtils.isFileExists(mVideoDirPath+downloadVideoName)){ + Logger.d(ImageAndVideoRotation.TAG, "have cache startPlay") + startPlay(Uri.fromFile(File(mVideoDirPath+downloadVideoName)).toString()) + return + } + startDownLoadVideo() + } + } + + private fun startDownLoadVideo(){ + //下载视频, 下载成功后再播放 + Logger.d(ImageAndVideoRotation.TAG, "startDownLoadVideo") + FileUtils.createFileDir(mVideoDirPath) + DownloadUtils.downLoad(context,fileNetPath,mVideoDirPath + ,downloadVideoName,5,downListener) + } + + fun startPlay(localVideoPath: String?){ + if (localVideoPath === "") return + try { + Logger.d(ImageAndVideoRotation.TAG, "startPlay") + gsyVideoOptionBuilder = GSYVideoOptionBuilder() + gsyVideoOptionBuilder +// ?.setUrl("file:///mnt/sdcard/downloads/$downloadVideoName") + ?.setUrl(localVideoPath) // "/data/user/0/com.mogo.launcher.f/files/video/" + ?.setPlayTag(downloadVideoName) + ?.setCacheWithPlay(false) + ?.setThumbPlay(false) + ?.build(videoViewPlayer) + + videoViewPlayer?.isFocusableInTouchMode = false + videoViewPlayer?.setVideoAllCallBack(mOnCompletionListener) + videoViewPlayer?.startPlayLogic() + }catch (e: Exception){ + Logger.d(ImageAndVideoRotation.TAG, "startPlay e = ${e.message}") + } + } + + fun onVideoReset(){ + videoViewPlayer?.onVideoReset() + mOnCompletionListener = null + } + + fun setPause() { + if (videoViewPlayer !== null) { + videoViewPlayer?.onVideoPause() + } + } + + fun setResume() { + if (videoViewPlayer !== null) { + videoViewPlayer?.onVideoResume() + } + } + + private val downListener = object : IDownload{ + override fun onStart(url: String?) { + setCacheImageViewVisible() + Logger.d(ImageAndVideoRotation.TAG, "download-onStart") + } + + override fun onPause(url: String?, threadBean: ThreadBean?) { + Logger.d(ImageAndVideoRotation.TAG, "download-onPause") +// UiThreadHandler.postDelayed(Runnable { +// startDownLoadVideo() +// },DOWNLOAD_DELAY) + // todo 测试下网络断掉是否会走onpause,且网络回复也不会继续下载 + } + + override fun onProgress(url: String?, length: Int) { + Logger.d(ImageAndVideoRotation.TAG, "download-onProgress== $length") + } + + override fun onFinished(url: String?, threadBean: ThreadBean?) { + Logger.d(ImageAndVideoRotation.TAG, "download-onFinished = $url") + if (url.equals(fileNetPath)){ //发现下载工具在断网又连网后,已完成的任务又都下载,跳转播放出现问题 + //下载完成 + ThreadUtils.runOnUiThread { + startPlay(Uri.fromFile(File(mVideoDirPath+downloadVideoName)).toString()) + } + }else{//如果当前文件不存在再次去下载当前的 + Logger.d(ImageAndVideoRotation.TAG, "download-onFinished = not current" + + ",currentUrl = $fileNetPath ") + if (FileUtils.isFileExists(mVideoDirPath+downloadVideoName)){ + Logger.d(ImageAndVideoRotation.TAG, "have download startPlay") + ThreadUtils.runOnUiThread { + startPlay(Uri.fromFile(File(mVideoDirPath+downloadVideoName)).toString()) + } + return + }else{ + startDownLoadVideo() + } + } + } + + override fun onError(url: String?, errorMsg: String?) { + Logger.d(ImageAndVideoRotation.TAG, "download-onError-$errorMsg") + //出错再次下载 + if (errorMsg != null) { + if (errorMsg.startsWith("initFailed")){ + startDownLoadVideo() + } + } + } + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/video/AdvanceViewPager.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/video/AdvanceViewPager.kt new file mode 100644 index 0000000000..1ec09195c3 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/video/AdvanceViewPager.kt @@ -0,0 +1,24 @@ +package com.mogo.och.bus.passenger.ui.widget.video + +import android.content.Context +import android.util.AttributeSet +import android.view.MotionEvent +import androidx.viewpager.widget.ViewPager + +/** + * @author: wangmingjun + * @date: 2023/2/21 + */ +class AdvanceViewPager: ViewPager{ + + constructor(context: Context) : super(context) + constructor(context: Context,attrs: AttributeSet?) : super(context,attrs) + + override fun onTouchEvent(ev: MotionEvent?): Boolean { + return false + } + + override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean { + return false + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/video/ImageAndVideoRotation.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/video/ImageAndVideoRotation.kt new file mode 100644 index 0000000000..92d3b3dbda --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/video/ImageAndVideoRotation.kt @@ -0,0 +1,47 @@ +package com.mogo.och.bus.passenger.ui.widget.video + +import android.annotation.SuppressLint +import android.content.Context +import android.util.AttributeSet +import android.widget.RelativeLayout +import androidx.viewpager.widget.ViewPager +/** + * @author: wangmingjun + * @date: 2023/2/6 + */ +class ImageAndVideoRotation @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null +) : RelativeLayout(context, attrs) { + + private var viewPager: AdvanceViewPager? = null + private var pagerAdapter: AdvancePagerAdapter? = null + + companion object { + const val TAG = "ImageAndVideoRotation" + } + + init { + initView() + } + + @SuppressLint("ClickableViewAccessibility") + private fun initView() { + viewPager = AdvanceViewPager(context) + pagerAdapter = AdvancePagerAdapter(context, viewPager!!) + viewPager?.adapter = pagerAdapter + + addView(viewPager, LayoutParams(-1, -1)) + } + + fun setData(list: MutableList){ + pagerAdapter?.setData(list) + } + + fun setPause(){ + pagerAdapter?.setPause() + } + + fun setResume(){ + pagerAdapter?.setResume() + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/video/RotationItem.kt b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/video/RotationItem.kt new file mode 100644 index 0000000000..ed788c6179 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/java/com/mogo/och/bus/passenger/ui/widget/video/RotationItem.kt @@ -0,0 +1,12 @@ +package com.mogo.och.bus.passenger.ui.widget.video + +/** + * @author: wangmingjun + * @date: 2023/2/6 + * type:0 图片 + * type:1 视频 + */ +data class RotationItem(var path: String, + var type: Int, + var cacheImgPath: String, + var title: String) \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/auto_button_bg.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/auto_button_bg.png new file mode 100644 index 0000000000..fb4ddc5279 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/auto_button_bg.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/bus_light_green_nor.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/bus_light_green_nor.png new file mode 100644 index 0000000000..bc9fed952d Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/bus_light_green_nor.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/bus_light_red_nor.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/bus_light_red_nor.png new file mode 100644 index 0000000000..8732508ded Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/bus_light_red_nor.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/bus_lightyellow_nor.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/bus_lightyellow_nor.png new file mode 100644 index 0000000000..bae01408fd Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/bus_lightyellow_nor.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/clock_bg.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/clock_bg.png new file mode 100644 index 0000000000..a380c3f3b7 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/clock_bg.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/img_drive_bg.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/img_drive_bg.png new file mode 100644 index 0000000000..7412ab3c90 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/img_drive_bg.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/img_line_bg.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/img_line_bg.png new file mode 100644 index 0000000000..dd78f6fc9e Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/img_line_bg.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/img_time_bg.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/img_time_bg.png new file mode 100644 index 0000000000..ba735834b6 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/img_time_bg.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_blue_tooth_close.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_blue_tooth_close.png new file mode 100644 index 0000000000..0c292d2cf3 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_blue_tooth_close.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_blue_tooth_open.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_blue_tooth_open.png new file mode 100644 index 0000000000..cccf9e10fa Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_blue_tooth_open.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_light_green_nor.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_light_green_nor.png new file mode 100644 index 0000000000..3135524a79 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_light_green_nor.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_light_red_nor.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_light_red_nor.png new file mode 100644 index 0000000000..e873c2b85e Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_light_red_nor.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_light_yellow_nor.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_light_yellow_nor.png new file mode 100644 index 0000000000..8046782601 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_light_yellow_nor.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_line_location_bg.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_line_location_bg.png new file mode 100644 index 0000000000..593db1abc5 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_line_location_bg.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_map_car_icon.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_map_car_icon.png new file mode 100644 index 0000000000..2520ae1c9e Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_map_car_icon.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_map_end_icon.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_map_end_icon.png new file mode 100644 index 0000000000..2efd3a52eb Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_map_end_icon.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_map_start_icon.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_map_start_icon.png new file mode 100644 index 0000000000..d7ab9231d9 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_map_start_icon.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_map_staton_icon.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_map_staton_icon.png new file mode 100644 index 0000000000..1314028434 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_map_staton_icon.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_p_video_holder.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_p_video_holder.png new file mode 100644 index 0000000000..d8c5951e43 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_p_video_holder.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_status_bar_logo.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_status_bar_logo.png new file mode 100644 index 0000000000..ad3bd7fda7 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_status_bar_logo.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_youzhuan_open.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_youzhuan_open.png new file mode 100644 index 0000000000..bbd2c12d90 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_youzhuan_open.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_youzhuan_un_open.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_youzhuan_un_open.png new file mode 100644 index 0000000000..7c0dcaabe1 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_youzhuan_un_open.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_zuozhuan_open.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_zuozhuan_open.png new file mode 100644 index 0000000000..9bbda22cb7 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_zuozhuan_open.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_zuozhuan_un_open.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_zuozhuan_un_open.png new file mode 100644 index 0000000000..7c33fddbd9 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable-nodpi/m2_zuozhuan_un_open.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/bg_dashed_line.xml b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/bg_dashed_line.xml new file mode 100644 index 0000000000..f6917017e5 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/bg_dashed_line.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/bg_driving_selector.xml b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/bg_driving_selector.xml new file mode 100644 index 0000000000..21a6524032 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/bg_driving_selector.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/bg_p_m2_auto.xml b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/bg_p_m2_auto.xml new file mode 100644 index 0000000000..0497ff212e --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/bg_p_m2_auto.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/bg_p_m2_traffic_light.xml b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/bg_p_m2_traffic_light.xml new file mode 100644 index 0000000000..5a27da20e0 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/bg_p_m2_traffic_light.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/bg_pnc.xml b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/bg_pnc.xml new file mode 100644 index 0000000000..0357ebb192 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/bg_pnc.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/brakelight_background_daytime.xml b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/brakelight_background_daytime.xml new file mode 100644 index 0000000000..b6cbdbd569 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/brakelight_background_daytime.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/bus_light_green_nor.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/bus_light_green_nor.png new file mode 100644 index 0000000000..bc9fed952d Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/bus_light_green_nor.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/bus_light_red_nor.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/bus_light_red_nor.png new file mode 100644 index 0000000000..8732508ded Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/bus_light_red_nor.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/bus_lightyellow_nor.png b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/bus_lightyellow_nor.png new file mode 100644 index 0000000000..bae01408fd Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/bus_lightyellow_nor.png differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/m2_power_seekbar_style.xml b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/m2_power_seekbar_style.xml new file mode 100644 index 0000000000..3ac0c761ba --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/res/drawable/m2_power_seekbar_style.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/m2_p_traffic_light_view.xml b/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/m2_p_traffic_light_view.xml new file mode 100644 index 0000000000..360a67883b --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/m2_p_traffic_light_view.xml @@ -0,0 +1,36 @@ + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/p_m2_driving_info_fragment.xml b/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/p_m2_driving_info_fragment.xml new file mode 100644 index 0000000000..eb8eed4b1f --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/p_m2_driving_info_fragment.xml @@ -0,0 +1,235 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/p_m2_fragment.xml b/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/p_m2_fragment.xml new file mode 100644 index 0000000000..c4a848c6bd --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/p_m2_fragment.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/p_m2_hpmap_fragment.xml b/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/p_m2_hpmap_fragment.xml new file mode 100644 index 0000000000..851d3a25bb --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/p_m2_hpmap_fragment.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/p_m2_video_fragment.xml b/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/p_m2_video_fragment.xml new file mode 100644 index 0000000000..6c82b8c9dc --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/p_m2_video_fragment.xml @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/p_m2_video_view.xml b/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/p_m2_video_view.xml new file mode 100644 index 0000000000..9d75478ee1 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/p_m2_video_view.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/p_m2_view_blue_tooth.xml b/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/p_m2_view_blue_tooth.xml new file mode 100644 index 0000000000..69ae14c394 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/p_m2_view_blue_tooth.xml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/p_m2_view_status_bar.xml b/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/p_m2_view_status_bar.xml new file mode 100644 index 0000000000..20461e6c5a --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/p_m2_view_status_bar.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/view_turn_light_status_daytime.xml b/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/view_turn_light_status_daytime.xml new file mode 100644 index 0000000000..3ba54be149 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/res/layout/view_turn_light_status_daytime.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/raw/station_marker.nt3d b/OCH/mogo-och-shuttle-passenger/src/m2/res/raw/station_marker.nt3d new file mode 100644 index 0000000000..a00207ba3f Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/m2/res/raw/station_marker.nt3d differ diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/values/colors.xml b/OCH/mogo-och-shuttle-passenger/src/m2/res/values/colors.xml new file mode 100644 index 0000000000..c752b78caf --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/res/values/colors.xml @@ -0,0 +1,26 @@ + + + #FFFFFF + #0B1E38 + #2D3E5F + + #BBDAFB + #0B1E38 + #5D7199 + #0B1E38 + #6B7EA6 + #2D3E5F + #A5D8FF + #1B2546 + #23355D + #374E7F + + #FFFFA28B + #FFDA1100 + #FF60FFD3 + #FF006D43 + #FFFFE198 + #FFFF9B00 + #59FFFFFF + #8895B7 + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/values/dimens.xml b/OCH/mogo-och-shuttle-passenger/src/m2/res/values/dimens.xml new file mode 100644 index 0000000000..ca8e0dcfc1 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/res/values/dimens.xml @@ -0,0 +1,5 @@ + + + 60dp + 40dp + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/m2/res/values/strings.xml b/OCH/mogo-och-shuttle-passenger/src/m2/res/values/strings.xml new file mode 100644 index 0000000000..e113235a28 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/m2/res/values/strings.xml @@ -0,0 +1,23 @@ + + + KM/H + 您已收车 + 暂无路线 + + + 到达站: + 下一站: + 始发站: + 请携带好随身物品下车。 + 欢迎乘坐蘑菇车联自动驾驶车。 + + m2_map_style.data + m2_map_style_extra.data + Auto + 下一站: + 已到站: + 暂无站点 + —公里 | —分钟 + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/main/AndroidManifest.xml b/OCH/mogo-och-shuttle-passenger/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..e0687231c1 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/main/AndroidManifest.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/main/assets/map_style.data b/OCH/mogo-och-shuttle-passenger/src/main/assets/map_style.data new file mode 100644 index 0000000000..ab077f9849 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/main/assets/map_style.data differ diff --git a/OCH/mogo-och-shuttle-passenger/src/main/assets/map_style_extra.data b/OCH/mogo-och-shuttle-passenger/src/main/assets/map_style_extra.data new file mode 100644 index 0000000000..01f7f2116e Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/main/assets/map_style_extra.data differ diff --git a/OCH/mogo-och-shuttle-passenger/src/main/java/com/mogo/och/bus/passenger/IMogoOCH.java b/OCH/mogo-och-shuttle-passenger/src/main/java/com/mogo/och/bus/passenger/IMogoOCH.java new file mode 100644 index 0000000000..fb146e17c3 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/main/java/com/mogo/och/bus/passenger/IMogoOCH.java @@ -0,0 +1,22 @@ +package com.mogo.och.bus.passenger; + +import androidx.annotation.IdRes; +import androidx.fragment.app.FragmentActivity; + +import com.mogo.eagle.core.function.api.base.IMoGoFunctionProvider; + +/** + * 网约车抽象接口 + * + * Created on 2022/3/29 + */ +interface IMogoOCH extends IMoGoFunctionProvider { + + /** + * 初始化网约车容器 + * + * @param activity + * @param containerId 容器ID + */ + void createCoverage(FragmentActivity activity, @IdRes int containerId); +} diff --git a/OCH/mogo-och-shuttle-passenger/src/main/java/com/mogo/och/bus/passenger/constant/BusPassengerConst.kt b/OCH/mogo-och-shuttle-passenger/src/main/java/com/mogo/och/bus/passenger/constant/BusPassengerConst.kt new file mode 100644 index 0000000000..88fbdc0127 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/main/java/com/mogo/och/bus/passenger/constant/BusPassengerConst.kt @@ -0,0 +1,38 @@ +package com.mogo.och.bus.passenger.constant + +import com.mogo.commons.debug.DebugConfig + +/** + * Created on 2021/12/6 + */ +class BusPassengerConst { + companion object { + + // OCH arouter 路由path + const val PATH = "/passenger/api" + + // 轮询line + const val LOOP_LINE_2S = 2 * 1000L + const val LOOP_LINE_1S = 1 * 1000L + const val LOOP_DELAY = 100L + + // 无状态 + const val STATION_STATUS_IDLE = 0 + // 已过站(历史站) + const val STATION_STATUS_LEAVING = 1 + // 到站(当前站) + const val STATION_STATUS_STOPPED = 2 + // 未到站(未到站) + const val STATION_STATUS_ARRIVING = 3 + + //bus平均速度 bus的平均里程:25km/h + const val BUS_AVERAGE_SPEED = 25 + //接驳/B2平均速度 bus的平均里程:10km/h + const val SHUTTLE_AVERAGE_SPEED = 10 + + // 订单总里程 + const val BUS_SP_KEY_ORDER_SUM_DIS = "BUS_SP_KEY_ORDER_SUM_DIS" + + const val QUERY_BUS_P_STATION_DELAY = 3 * 1000L + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/main/java/com/mogo/och/bus/passenger/utils/BusPassengerMapAssetStyleUtil.java b/OCH/mogo-och-shuttle-passenger/src/main/java/com/mogo/och/bus/passenger/utils/BusPassengerMapAssetStyleUtil.java new file mode 100644 index 0000000000..edab28cb78 --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/main/java/com/mogo/och/bus/passenger/utils/BusPassengerMapAssetStyleUtil.java @@ -0,0 +1,61 @@ +package com.mogo.och.bus.passenger.utils; + + +import android.content.Context; + +import java.io.IOException; +import java.io.InputStream; + +/** + * @author donghongyu + * @date 12/18/20 5:37 PM + */ +public class BusPassengerMapAssetStyleUtil { + + public static byte[] getAssetsStyle(Context context,String fileName) { + byte[] buffer1 = null; + InputStream is1 = null; + try { + is1 = context.getResources().getAssets().open(fileName); //eg. over_view_style.data + int lenght1 = is1.available(); + buffer1 = new byte[lenght1]; + is1.read(buffer1); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (is1 != null) { + is1.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + return buffer1; + } + + + public static byte[] getAssetsExtraStyle(Context context, String fileName) { + byte[] buffer1 = null; + InputStream is1 = null; + try { + is1 = context.getResources().getAssets().open(fileName); //eg. over_view_style_extra.data + int lenght1 = is1.available(); + buffer1 = new byte[lenght1]; + is1.read(buffer1); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + if (is1 != null) { + is1.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + return buffer1; + } + + +} diff --git a/OCH/mogo-och-shuttle-passenger/src/main/java/com/mogo/och/bus/passenger/utils/DimenUtil.kt b/OCH/mogo-och-shuttle-passenger/src/main/java/com/mogo/och/bus/passenger/utils/DimenUtil.kt new file mode 100644 index 0000000000..4ad4e9a2ba --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/main/java/com/mogo/och/bus/passenger/utils/DimenUtil.kt @@ -0,0 +1,13 @@ +package com.mogo.och.bus.passenger.utils + +import android.content.res.Resources + +/** + * @author: wangmingjun + * @date: 2022/1/21 + */ +object DimenUtil{ + fun dp2px(value:Float):Float{ + return (0.5f + value * Resources.getSystem().displayMetrics.density) + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle-passenger/src/main/res/raw/bus_di.mp3 b/OCH/mogo-och-shuttle-passenger/src/main/res/raw/bus_di.mp3 new file mode 100644 index 0000000000..15b31ed247 Binary files /dev/null and b/OCH/mogo-och-shuttle-passenger/src/main/res/raw/bus_di.mp3 differ diff --git a/OCH/mogo-och-shuttle-passenger/src/test/java/com/mogo/och/bus/passenger/ExampleUnitTest.java b/OCH/mogo-och-shuttle-passenger/src/test/java/com/mogo/och/bus/passenger/ExampleUnitTest.java new file mode 100644 index 0000000000..d940b2948f --- /dev/null +++ b/OCH/mogo-och-shuttle-passenger/src/test/java/com/mogo/och/bus/passenger/ExampleUnitTest.java @@ -0,0 +1,15 @@ +package com.mogo.och.bus.passenger; + +import org.junit.Test; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() { + + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/.gitignore b/OCH/mogo-och-shuttle/.gitignore new file mode 100644 index 0000000000..42afabfd2a --- /dev/null +++ b/OCH/mogo-och-shuttle/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/build.gradle b/OCH/mogo-och-shuttle/build.gradle new file mode 100644 index 0000000000..1d06e3b890 --- /dev/null +++ b/OCH/mogo-och-shuttle/build.gradle @@ -0,0 +1,63 @@ +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 rootProject.ext.dependencies.androidxrecyclerview + compileOnly rootProject.ext.dependencies.recyclerviewadapterhelper + + implementation project(":OCH:mogo-och-common-module") + compileOnly project(":libraries:mogo-map") + +} + +apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString() \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/consumer-rules.pro b/OCH/mogo-och-shuttle/consumer-rules.pro new file mode 100644 index 0000000000..e69de29bb2 diff --git a/OCH/mogo-och-shuttle/gradle.properties b/OCH/mogo-och-shuttle/gradle.properties new file mode 100644 index 0000000000..dd5c44ee62 --- /dev/null +++ b/OCH/mogo-och-shuttle/gradle.properties @@ -0,0 +1,3 @@ +GROUP=com.mogo.och +POM_ARTIFACT_ID=och-bus +VERSION_CODE=1 diff --git a/OCH/mogo-och-shuttle/proguard-rules.pro b/OCH/mogo-och-shuttle/proguard-rules.pro new file mode 100644 index 0000000000..481bb43481 --- /dev/null +++ b/OCH/mogo-och-shuttle/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/AndroidManifest.xml b/OCH/mogo-och-shuttle/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..76856fd226 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/AndroidManifest.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/BusProvider.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/BusProvider.java new file mode 100644 index 0000000000..e8f3e0f280 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/BusProvider.java @@ -0,0 +1,101 @@ + +package com.mogo.och.bus; + +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 androidx.fragment.app.FragmentManager; + +import com.alibaba.android.arouter.facade.annotation.Route; +import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager; +import com.mogo.eagle.core.function.call.setting.CallerMoGoUiSettingManager; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.och.bus.constant.BusConst; +import com.mogo.och.bus.fragment.BusFragment; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * 网约车小巴业务实现入口 + * + * @author tongchenfei + */ +@Route(path = BusConst.PATH) +public class BusProvider implements IMogoOCH { + + private static final String TAG = "BusProvider"; + + private BusFragment busFragment; + private int containerId; + private FragmentActivity activity; + + /** + * 进入鹰眼模式,设置手势缩放地图失效 + */ + private void stepIntoVrMode() { + CallerLogger.INSTANCE.d(M_BUS + TAG, "进入vr模式"); + CallerMoGoUiSettingManager.INSTANCE.stepInNightMode();//夜间模式 状态栏字体颜色变黑 + } + + @Override + public void init(Context context) { + } + + private void showFragment() { + FragmentManager supportFragmentManager = activity.getSupportFragmentManager(); + if (busFragment == null) { + CallerLogger.INSTANCE.d(TAG, "准备add fragment======"); + Fragment fragmentByTag = supportFragmentManager.findFragmentByTag(BusFragment.TAG); + if (fragmentByTag instanceof BusFragment) { + busFragment = (BusFragment) fragmentByTag; + } else { + busFragment = new BusFragment(); + } + if(!busFragment.isAdded()) { + supportFragmentManager.beginTransaction().add(containerId, busFragment, BusFragment.TAG).commitAllowingStateLoss(); + } + return; + } + CallerLogger.INSTANCE.d(TAG, "准备show fragment"); + supportFragmentManager.beginTransaction().show(busFragment).commitAllowingStateLoss(); + } + + private void hideFragment() { + if (busFragment != null) { + CallerLogger.INSTANCE.d(TAG, "准备hide fragment"); + activity.getSupportFragmentManager().beginTransaction().hide(busFragment).commitAllowingStateLoss(); + } + + } + + @Override + public void createCoverage(FragmentActivity activity, int containerId) { + + } + + @NotNull + @Override + public String getFunctionName() { + return null; + } + + @Nullable + @Override + public Fragment createCoverage(@Nullable FragmentActivity fragmentActivity, @Nullable Integer integer) { + this.containerId = integer; + this.activity = fragmentActivity; + showFragment(); + return null; + } + + @Override + public void onDestroy() { + //若不调用finish, 设置中打开关闭UITouch,会造成och fragment 重叠 + if (activity == null) return; + activity.finish(); + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/IMogoOCH.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/IMogoOCH.java new file mode 100644 index 0000000000..073f7fcc29 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/IMogoOCH.java @@ -0,0 +1,24 @@ +package com.mogo.och.bus; + +import androidx.annotation.IdRes; +import androidx.fragment.app.FragmentActivity; + +import com.mogo.eagle.core.function.api.base.IMoGoFunctionProvider; + +public +/** + * @author congtaowang + * @since 2021/1/15 + * + * 网约车抽象接口 + */ +interface IMogoOCH extends IMoGoFunctionProvider { + + /** + * 初始化网约车容器 + * + * @param activity + * @param containerId 容器ID + */ + void createCoverage(FragmentActivity activity, @IdRes int containerId); +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusCloseTaskRequest.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusCloseTaskRequest.java new file mode 100644 index 0000000000..d8a11924af --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusCloseTaskRequest.java @@ -0,0 +1,20 @@ +package com.mogo.och.bus.bean; + +import com.mogo.cloud.passport.MoGoAiCloudClientConfig; + +/** + * 中止/结束任务请求 + */ +public class BusCloseTaskRequest { + + private String sn; + private int taskId; + public BusCloseTaskRequest(int taskId) { + this.sn = MoGoAiCloudClientConfig.getInstance().getSn(); + this.taskId = taskId; + } + + public String getSn() { + return sn; + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusOperationStatusRequest.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusOperationStatusRequest.java new file mode 100644 index 0000000000..96d4435ef4 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusOperationStatusRequest.java @@ -0,0 +1,42 @@ +package com.mogo.och.bus.bean; + +import com.mogo.cloud.passport.MoGoAiCloudClientConfig; + +public +/** + * @author congtaowang + * @since 2021/3/22 + * + * 小巴车运营状态请求参数 + */ +class BusOperationStatusRequest { + + private String sn; + private double lat; + private double lon; + public BusOperationStatusRequest(double lon, double lat) { + this.sn = MoGoAiCloudClientConfig.getInstance().getSn(); + this.lat = lat; + this.lon = lon; + } + public void setLat(double lat) { + this.lat = lat; + } + + public void setLon(double lon) { + this.lon = lon; + } + + public String getSn() { + return sn; + } + + public double getLat() { + return lat; + } + + public double getLon() { + return lon; + } + +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusOrderBean.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusOrderBean.java new file mode 100644 index 0000000000..85c3a1da58 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusOrderBean.java @@ -0,0 +1,86 @@ +package com.mogo.och.bus.bean; + +/** + * @author congtaowang + * @since 2021/3/23 + *

+ * 小巴订单 + */ +public class BusOrderBean { + + /** + * orderNo number + * passengerPhone string 下单用户电话 + * startStationId integer 开始站点 + * startStationName string + * endStationId integer 结束站点 + * endStationName string + */ + + private String orderNo; + private String passengerPhone; + private int startStationId;//乘客上车点 + private String startStationName; + private String endStationName; + private int endStationId;//乘客下车点 + + public void setOrderNo(String orderNo) { + this.orderNo = orderNo; + } + + public void setPassengerPhone(String passengerPhone) { + this.passengerPhone = passengerPhone; + } + + public void setStartStationId(int startStationId) { + this.startStationId = startStationId; + } + + public void setStartStationName(String startStationName) { + this.startStationName = startStationName; + } + + public void setEndStationName(String endStationName) { + this.endStationName = endStationName; + } + + public void setEndStationId(int endStationId) { + this.endStationId = endStationId; + } + + public String getOrderNo() { + return orderNo; + } + + public String getPassengerPhone() { + return passengerPhone; + } + + public int getStartStationId() { + return startStationId; + } + + public String getStartStationName() { + return startStationName; + } + + public String getEndStationName() { + return endStationName; + } + + public int getEndStationId() { + return endStationId; + } + + @Override + public String toString() { + return "BusOrderBean{" + + "orderNo=" + orderNo + + ", passengerPhone='" + passengerPhone + '\'' + + ", startStationId=" + startStationId + + ", startStationName='" + startStationName + '\'' + + ", endStationName='" + endStationName + '\'' + + ", endStationId=" + endStationId + + '}'; + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusQueryLineStationsRequest.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusQueryLineStationsRequest.java new file mode 100644 index 0000000000..adf7878ec5 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusQueryLineStationsRequest.java @@ -0,0 +1,17 @@ +package com.mogo.och.bus.bean; + +import com.mogo.cloud.passport.MoGoAiCloudClientConfig; + +/** + * @author congtaowang + * @since 2021/3/22 + * + * 根据车机行驶线路站点信息 + */ +public class BusQueryLineStationsRequest { + + private String sn; + public BusQueryLineStationsRequest() { + this.sn = MoGoAiCloudClientConfig.getInstance().getSn(); + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusQueryLineTaskResponse.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusQueryLineTaskResponse.java new file mode 100644 index 0000000000..4911c3cf99 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusQueryLineTaskResponse.java @@ -0,0 +1,19 @@ +package com.mogo.och.bus.bean; + +import com.mogo.eagle.core.data.BaseData; + +import java.util.List; + +/** + * @author: wangmingjun + * @date: 2022/2/9 + */ +public class BusQueryLineTaskResponse extends BaseData { + + public List data; + + public static class Result { + public int id; + public long taskStartTime; + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusQueryLinesResponse.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusQueryLinesResponse.java new file mode 100644 index 0000000000..17540e3eed --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusQueryLinesResponse.java @@ -0,0 +1,27 @@ +package com.mogo.och.bus.bean; + +import com.mogo.eagle.core.data.BaseData; + +import java.util.List; + +/** + * @author: wangmingjun + * @date: 2022/2/9 + */ +public class BusQueryLinesResponse extends BaseData { + public List data; + + public static class Result { + + public int lineId;//线路id + public String name;//线路名字 + public int choose; // 1:绑定 2:未被绑定 + public String startSiteName;//始发站名称 + public String endSiteName;//终点名称 + + public boolean open;//true 打开状态 false + public boolean haveTask; + + public List taskList; + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusQueryWriteOffPassengersResponse.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusQueryWriteOffPassengersResponse.java new file mode 100644 index 0000000000..36a5e3b409 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusQueryWriteOffPassengersResponse.java @@ -0,0 +1,13 @@ +package com.mogo.och.bus.bean; + +import com.mogo.eagle.core.data.BaseData; + +import java.util.List; + +/** + * @author: wangmingjun + * @date: 2021/10/19 + */ +public class BusQueryWriteOffPassengersResponse extends BaseData { + public List data; +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusResetDrivingLineRequest.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusResetDrivingLineRequest.java new file mode 100644 index 0000000000..7de15dae2c --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusResetDrivingLineRequest.java @@ -0,0 +1,17 @@ +package com.mogo.och.bus.bean; + +import com.mogo.cloud.passport.MoGoAiCloudClientConfig; + +/** + * @author: wangmingjun + * @date: 2021/10/18 + */ +public class BusResetDrivingLineRequest { + public String sn; + public int taskId; //切换到的线路id + + public BusResetDrivingLineRequest(int taskId) { + this.sn = MoGoAiCloudClientConfig.getInstance().getSn(); + this.taskId = taskId; + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusResetLineStatusRequest.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusResetLineStatusRequest.java new file mode 100644 index 0000000000..595ceafce3 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusResetLineStatusRequest.java @@ -0,0 +1,24 @@ +package com.mogo.och.bus.bean; + +import com.mogo.cloud.passport.MoGoAiCloudClientConfig; + +public +/** + * @author congtaowang + * @since 2021/3/22 + * + * 小巴车重置路线状态请求参数 + */ +class BusResetLineStatusRequest { + + private String sn; + public BusResetLineStatusRequest() { + this.sn = MoGoAiCloudClientConfig.getInstance().getSn(); + } + + public String getSn() { + return sn; + } + + +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusRoutePlanningUpdateReqBean.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusRoutePlanningUpdateReqBean.java new file mode 100644 index 0000000000..080e7d47bd --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusRoutePlanningUpdateReqBean.java @@ -0,0 +1,30 @@ +package com.mogo.och.bus.bean; + +import java.util.List; + +/** + * Created by pangfan on 2021/8/19 + * + * 订单状态更新请求数据结构 + */ +public class BusRoutePlanningUpdateReqBean { + public String sn; + public int lineId; + public int startSiteId; + public int endSiteId; + public List points; + + public static class Result { + public Double latitude; + public Double longitude; + } + + public BusRoutePlanningUpdateReqBean(String sn, int lineId, int startSiteId + , int endSiteId, List points) { + this.sn = sn; + this.lineId = lineId; + this.startSiteId = startSiteId; + this.endSiteId = endSiteId; + this.points = points; + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusRoutesResult.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusRoutesResult.java new file mode 100644 index 0000000000..4b652d30df --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusRoutesResult.java @@ -0,0 +1,80 @@ +package com.mogo.och.bus.bean; + +import java.util.List; + +/** + * 网约车小巴路线接口返回接口数据封装 + * + * @author tongchenfei + */ +public class BusRoutesResult { + private List sites; + private int lineId; + private String name; + private int lineType; //线路类型,0:环形 + private String description; + private int status; + private long taskTime; //线路时间班次 + private int taskId;// 线路班次id + + //线路轨迹相关字段 + 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 int getTaskId() { + return taskId; + } + + public String getName() { + return name; + } + + public List getSites() { + return sites; + } + + public void setSite(List site) { + this.sites = sites; + } + + public long getTaskTime() { + return taskTime; + } + + @Override + public String toString() { + return "BusRoutesResult{" + + "sites=" + sites + + ", lineId=" + lineId + + ", name='" + name + '\'' + + ", taskTime='" + taskTime + '\'' + + ", lineType=" + lineType + + ", description='" + description + '\'' + + ", status=" + status + + ", csvFileUrl='" + csvFileUrl + '\'' + + ", csvFileMd5='" + csvFileMd5 + '\'' + + ", txtFileUrl='" + txtFileUrl + '\'' + + ", txtFileMd5='" + txtFileMd5 + '\'' + + ", contrailSaveTime=" + contrailSaveTime + + ", carModel='" + carModel + '\'' + + ", csvFileUrlDPQP='" + csvFileUrlDPQP + '\'' + + ", csvFileMd5DPQP='" + csvFileMd5DPQP + '\'' + + ", txtFileUrlDPQP='" + txtFileUrlDPQP + '\'' + + ", txtFileMd5DPQP='" + txtFileMd5DPQP + '\'' + + ", contrailSaveTimeDPQP=" + contrailSaveTimeDPQP + + '}'; + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusUpdateSiteStatusRequest.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusUpdateSiteStatusRequest.java new file mode 100644 index 0000000000..93ff4b5457 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusUpdateSiteStatusRequest.java @@ -0,0 +1,24 @@ +package com.mogo.och.bus.bean; + +import com.mogo.cloud.passport.MoGoAiCloudClientConfig; + +/** + * @author congtaowang + * @since 2021/3/22 + * + * 小巴车运营状态请求参数 + */ +public class BusUpdateSiteStatusRequest { + + public String sn; + public int taskId; + public int seq;//站点序号 + public int siteId;//站点id + + public BusUpdateSiteStatusRequest(int taskId,int siteId,int seq) { + this.sn = MoGoAiCloudClientConfig.getInstance().getSn(); + this.seq = seq; + this.siteId = siteId; + this.taskId = taskId; + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusWriteOffPassengersQueryRequest.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusWriteOffPassengersQueryRequest.java new file mode 100644 index 0000000000..6f07456c78 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/BusWriteOffPassengersQueryRequest.java @@ -0,0 +1,24 @@ +package com.mogo.och.bus.bean; + +import com.mogo.cloud.passport.MoGoAiCloudClientConfig; + +/** + * 查询核销乘客 + */ +public class BusWriteOffPassengersQueryRequest { + + private String sn; + private int taskId; + private int siteId; + private long verificationTime; + public BusWriteOffPassengersQueryRequest(int taskId, int siteId,long prePassengerTime) { + this.sn = MoGoAiCloudClientConfig.getInstance().getSn(); + this.taskId = taskId; + this.siteId = siteId; + this.verificationTime = prePassengerTime; + } + + public String getSn() { + return sn; + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/CarHeartbeatReqBean.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/CarHeartbeatReqBean.java new file mode 100644 index 0000000000..dcacb5e380 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/CarHeartbeatReqBean.java @@ -0,0 +1,26 @@ +package com.mogo.och.bus.bean; + +import com.mogo.och.bus.constant.BusConst; + +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) (BusConst.LOOP_PERIOD_60S / 1000); + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/QueryLeaveAwayPassengersRequest.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/QueryLeaveAwayPassengersRequest.java new file mode 100644 index 0000000000..443fd76211 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/QueryLeaveAwayPassengersRequest.java @@ -0,0 +1,36 @@ +package com.mogo.och.bus.bean; + +import com.mogo.cloud.passport.MoGoAiCloudClientConfig; + +/** + * 查询下车乘客请求参数 + * + * @author tongchenfei + */ +public class QueryLeaveAwayPassengersRequest { + private String sn; + private int seq; //站点在线路中的序号 + private int siteId; //站点id + + public QueryLeaveAwayPassengersRequest(int seq, int siteId) { + this.sn = MoGoAiCloudClientConfig.getInstance().getSn(); + this.seq = seq; + this.siteId = siteId; + } + + public void setSeq(int seq) { + this.seq = seq; + } + + public void setSiteId(int siteId) { + this.siteId = siteId; + } + + public int getSeq() { + return seq; + } + + public int getSiteId() { + return siteId; + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/QueryLeaveAwayPassengersResponse.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/QueryLeaveAwayPassengersResponse.java new file mode 100644 index 0000000000..98105058b8 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/QueryLeaveAwayPassengersResponse.java @@ -0,0 +1,60 @@ +package com.mogo.och.bus.bean; + +import com.mogo.eagle.core.data.BaseData; + +import java.util.List; + +public +/** + * @author congtaowang + * @since 2021/3/26 + * + * 到站查询下车乘客 + */ +class QueryLeaveAwayPassengersResponse extends BaseData { + + public Result data; + + public static class Result { + + public List< LeaveAwayPassenger > orders; + } + + public static class LeaveAwayPassenger { + /** + * orderNo: 订单no + * orderStatus: 订单状态 + * orderType:订单类型:0及时,1预约 + * bookingTime:预计用车时间 + * businessType:订单运营类型 9:taxi,10:bus + * startSiteId: 起点站点id + * userPhone: 乘客联系方式 + * startSitePoint:开始站点坐标 + * startSiteAddr:开始地址 + * endSiteId:结束站点id + * endSitePoint:结束站点坐标 + * carNumber:车牌号 + * createTime: 创建时间 + * startTime:开始时间 + * startSiteGcjPoint:高精坐标 + * endSiteGcjPoint: + */ +//todo 目前是需要乘客电话来通知乘客下车 目前后台没有乘客信息userPhone + public String orderNo; + public int orderStatus; + public int orderType; + public long bookingTime; + public int businessType; + public int startSiteId; + public String passengerPhone; + public List startSitePoint; + public String startSiteAddr; + public int endSiteId; + public List endSitePoint; + public String carNumber; + public long createTime; + public long startTime; + public List< Double > startSiteGcjPoint; + public List< Double > endSiteGcjPoint; + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/WriteOffPassenger.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/WriteOffPassenger.java new file mode 100644 index 0000000000..11ac15e305 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/bean/WriteOffPassenger.java @@ -0,0 +1,14 @@ +package com.mogo.och.bus.bean; + +import java.io.Serializable; + +/** + * @author: wangmingjun + * @date: 2022/9/23 + */ +public class WriteOffPassenger implements Serializable { + public String phone; + public String orderNo; + public int passengerSize; + public long writeOffTime; +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/callback/IBusADASStatusCallback.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/callback/IBusADASStatusCallback.java new file mode 100644 index 0000000000..186fc0b5f4 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/callback/IBusADASStatusCallback.java @@ -0,0 +1,11 @@ +package com.mogo.och.bus.callback; + +/** + * Created on 2021/9/8 + * + * Model->Presenter回调:ADAS相关(自动驾驶状态回调,到达终点等等) + */ +public interface IBusADASStatusCallback { + //自驾返回失败 + void onStartAdasFailure(); +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/callback/IBusControllerStatusCallback.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/callback/IBusControllerStatusCallback.java new file mode 100644 index 0000000000..e10afc44e7 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/callback/IBusControllerStatusCallback.java @@ -0,0 +1,17 @@ +package com.mogo.och.bus.callback; + +import com.mogo.eagle.core.data.map.MogoLocation; + +/** + * Created on 2021/9/10 + * + * Model->Presenter回调:状态控制器监听(accOn、adas ui show、voice ui show、push ui show、v2x ui show等等) + */ +public interface IBusControllerStatusCallback { + // 是否vr map模式 + void onVRModeChanged(boolean isVRMode); + // 自车定位 + void onCarLocationChanged(MogoLocation location); + //开始开启自动驾驶 + void startOpenAutopilot(); +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/callback/IBusLinesCallback.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/callback/IBusLinesCallback.java new file mode 100644 index 0000000000..8250b337c5 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/callback/IBusLinesCallback.java @@ -0,0 +1,14 @@ +package com.mogo.och.bus.callback; + +import com.mogo.och.bus.bean.BusQueryLineTaskResponse; +import com.mogo.och.bus.bean.BusQueryLinesResponse; + +/** + * @author: wangmingjun + * @date: 2022/2/9 + */ +public interface IBusLinesCallback { + void onBusLinesChange(BusQueryLinesResponse lines); + void onChangeLineIdSuccess(); + void onBusLineTasks(BusQueryLineTaskResponse o, int position,boolean autoRefresh); +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/callback/IPassengerCallback.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/callback/IPassengerCallback.java new file mode 100644 index 0000000000..98f4498282 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/callback/IPassengerCallback.java @@ -0,0 +1,11 @@ +package com.mogo.och.bus.callback; + +import com.mogo.och.bus.bean.WriteOffPassenger; + +/** + * @author: wangmingjun + * @date: 2022/9/26 + */ +public interface IPassengerCallback { + void playPassenger(WriteOffPassenger passenger); +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/callback/IRefreshBusStationsCallback.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/callback/IRefreshBusStationsCallback.java new file mode 100644 index 0000000000..03fcce170f --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/callback/IRefreshBusStationsCallback.java @@ -0,0 +1,21 @@ +package com.mogo.och.bus.callback; + +import java.util.List; + +/** + * @author: wangmingjun + * @date: 2021/10/22 + */ +public interface IRefreshBusStationsCallback { + void updateBusTaskStatus(String lineName,String lintTime, + List stationList, + int arrivingOrArrivedIndex, + boolean isArrived); + + /** + * 结束清理一遍、选择任务后清理一遍 + */ + void clearBusStationsMarkers(); + + void updateEmptyUi(); +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/callback/ISlidePannelHideCallback.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/callback/ISlidePannelHideCallback.java new file mode 100644 index 0000000000..16e6893135 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/callback/ISlidePannelHideCallback.java @@ -0,0 +1,9 @@ +package com.mogo.och.bus.callback; + +/** + * @author: wangmingjun + * @date: 2021/10/22 + */ +public interface ISlidePannelHideCallback { + void hideSlidePanel(); +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/constant/BusConst.kt b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/constant/BusConst.kt new file mode 100644 index 0000000000..7eadb3d41f --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/constant/BusConst.kt @@ -0,0 +1,77 @@ +package com.mogo.och.bus.constant + +import com.mogo.commons.debug.DebugConfig + +/** + * Created on 2021/12/6 + */ +class BusConst { + companion object { + // OCH arouter 路由path + const val PATH = "/driver/api" + + // 测试用的广播 + const val BROADCAST_TEST_BUS_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 BUS_START_MAP_MAKER = "bus_start_map_maker"; + //终点UUID + const val BUS_END_MAP_MAKER = "bus_end_map_maker"; + + // 埋点key:接管后点击'自动驾驶'按钮启动 + const val EVENT_KEY_RESTART_AUTOPILOT = "event_key_och_bus_restart_autopilot" + // 埋点key:开始服务开启自动驾驶(成功/失败) + const val EVENT_KEY_START_SERVICE = "event_key_och_bus_start_service" + const val EVENT_PARAM_SN = "sn" + const val EVENT_PARAM_TIME = "time" + const val EVENT_PARAM_START_NAME = "start_name" + const val EVENT_PARAM_END_NAME = "end_name" + const val EVENT_PARAM_LINE_ID = "line_id" + const val EVENT_PARAM_START_RESULT = "start_autopilot" // true/false + const val EVENT_PARAM_START_FAILURE_CODE = "start_autopilot_failure_code" // 启动自驾失败code + const val EVENT_PARAM_START_FAILURE_MSG = "start_autopilot_failure_msg" // 启动自驾失败原因 + const val EVENT_PARAM_PLATE_NUM = "plate_number" // 车牌号 + const val EVENT_PARAM_ENV_ONLINE = "env_online" // 是否线上环境:true/false + // 埋点key:开启自动驾驶前已识别的异常,会导致无法开启自驾 + const val EVENT_KEY_AP_UNABLE_START_REASON = "event_key_och_bus_ap_unable_start_reason" + const val EVENT_PARAM_UNABLE_START_REASON = "unable_start_reason"; + + /** + * 订单起终点Marker类型 + */ + const val TYPE_MARKER_BUS_ORDER = "TYPE_MARKER_BUS_ORDER" + + const val TIMER_START_AUTOPILOT_INTERVAL = 20 * 1000L + + //围栏到站 暂定10米 + const val ARRIVE_AT_END_STATION_DISTANCE = 10 + + // 轮询 + const val LOOP_PASSENGER_5S = 5 * 1000L + const val LOOP_PASSENGER_2S = 2 * 1000L + const val LOOP_PASSENGER_1S = 1 * 1000L + const val LOOP_DELAY_500 = 500L + + const val DELAY_10S = 10 * 1000L + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/constant/URLConst.kt b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/constant/URLConst.kt new file mode 100644 index 0000000000..dce7719222 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/constant/URLConst.kt @@ -0,0 +1,12 @@ +package com.mogo.och.bus.constant + +import com.mogo.commons.debug.DebugConfig + +/** + * Created on 2021/12/6 + */ +class URLConst { + companion object { + + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/fragment/BaseBusTabFragment.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/fragment/BaseBusTabFragment.java new file mode 100644 index 0000000000..59820ddffe --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/fragment/BaseBusTabFragment.java @@ -0,0 +1,648 @@ +package com.mogo.och.bus.fragment; + +import static com.mogo.och.bus.constant.BusConst.TIMER_START_AUTOPILOT_INTERVAL; + +import android.animation.ObjectAnimator; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +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.mvp.IView; +import com.mogo.commons.mvp.MvpFragment; +import com.mogo.commons.mvp.Presenter; +import com.mogo.eagle.core.data.config.FunctionBuildConfig; +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.call.map.CallerMapUIServiceManager; +import com.mogo.eagle.core.function.call.map.CallerVisualAngleManager; +import com.mogo.eagle.core.function.hmi.ui.msgbox.DriverMsgBoxBubbleView; +import com.mogo.eagle.core.function.hmi.ui.msgbox.DriverMsgBoxButtonView; +import com.mogo.eagle.core.function.hmi.ui.msgbox.DriverMsgBoxListView; +import com.mogo.eagle.core.function.hmi.ui.widget.TrafficDataView; +import com.mogo.eagle.core.function.smp.view.SmallMapView; +import com.mogo.eagle.core.function.view.MapBizView; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.eagle.core.utilcode.mogo.view.OnPreventFastClickListener; +import com.mogo.eagle.core.utilcode.util.UiThreadHandler; +import com.mogo.map.MogoMapUIController; +import com.mogo.map.listener.IMogoMapListener; +import com.mogo.map.listener.MogoMapListenerHandler; +import com.mogo.map.uicontroller.IMogoMapUIController; +import com.mogo.map.uicontroller.VisualAngleMode; +import com.mogo.och.bus.R; +import com.mogo.och.bus.bean.BusRoutesResult; +import com.mogo.och.bus.model.OrderModel; +import com.mogo.och.bus.util.BDRouteDataTestUtils; +import com.mogo.och.bus.view.SlidePanelView; +import com.mogo.och.common.module.utils.SoundPoolHelper; + +import org.greenrobot.eventbus.EventBus; + +import java.util.Objects; + +import bag_manager.BagManagerOuterClass; +import mogo.telematics.pad.MessagePad; +import record_cache.RecordPanelOuterClass; + +/** + * 网约车基础Fragment,主要负责布局通用界面,处理站点面板和通话面板互斥情况 + *

+ * 部分业务放在了此处处理 + * + * @author tongchenfei + */ +public abstract class BaseBusTabFragment> extends MvpFragment implements IMogoMapListener, IMoGoAutopilotRecordListener { + + private static final String TAG = "BaseBusTabFragment"; + + protected SlidePanelView slidePanelView; + private RelativeLayout ctvAutopilotStatus; + private ImageView ctvAutopilotStatusIv; + private TextView ctvAutopilotStatusTv; + protected TextView tvArrived; + protected RelativeLayout mSettingBtn; + protected RelativeLayout mBadcaseBtn; + protected RelativeLayout mAICollectBtn; + private FrameLayout flStationPanelContainer; + private MapBizView mapBizView; + private Group groupTestPanel; + private TrafficDataView mTrafficDataView; + // private BusTrafficLightView mTrafficLightView; + + //远景和中景的切换 + private ImageView mSwitchMapModeImage; + private LinearLayout mSwitchMapModeLayout; + + protected SmallMapView smallMapView; + + //消息盒子 + private DriverMsgBoxButtonView viewDriverMsgBoxButton; + private DriverMsgBoxListView viewDriverMsgBoxList; + private DriverMsgBoxBubbleView viewDriverMsgBoxBubble; + + private ObjectAnimator autopilotLoadingAnimator; + + public boolean isAnimateRunning = false; + + /** + * 滑动按钮触发的事件 + */ + private final SlidePanelView.OnSlidePanelMoveToEndListener onSlideToEndListener = () -> { + // 此处做一个代理,处理一下共有情况 + if (getSlidePanelOnEndListener() != null) { + getSlidePanelOnEndListener().moveToEnd(); + } + }; + + @Override + protected int getLayoutId() { + return R.layout.bus_base_fragment; + } + + @Override + protected void initViews() { + mapBizView = findViewById(R.id.mapBizView); + 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.bus_autopilot_btn_iv); + ctvAutopilotStatusTv = findViewById(R.id.bus_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); + tvArrived = findViewById(R.id.module_mogo_och_arrived_tv); + + mTrafficDataView = (TrafficDataView) findViewById(R.id.bus_arc); + + LayoutInflater.from(getContext()).inflate(getStationPanelViewId(), flStationPanelContainer); + slidePanelView.setOnSlidePanelMoveToEndListener(onSlideToEndListener); + + mSwitchMapModeLayout = findViewById(R.id.bus_switch_model_layout); + mSwitchMapModeImage = findViewById(R.id.bus_switch_model_icon); + updateSwitchMapIcon(); + + mSwitchMapModeLayout.setOnClickListener(new OnPreventFastClickListener() { + @Override + public void onClickImpl(View v) { + + IMogoMapUIController controller = CallerMapUIServiceManager.INSTANCE.getMapUIController(); + if (controller != null) { + //切换地图的远近视图 + if (controller.getCurrentMapVisualAngle().isLongSight()) { + CallerVisualAngleManager.INSTANCE.updateLongSightLevel(false); + Objects.requireNonNull(CallerMapUIServiceManager.INSTANCE.getMapUIController()).setLockMode(true); + controller.changeMapVisualAngle(VisualAngleMode.MODE_MEDIUM_SIGHT, null); + mSwitchMapModeImage.setImageResource(R.drawable.bus_switch_map_medium); + } else if (controller.getCurrentMapVisualAngle().isMediumSight()) { + CallerVisualAngleManager.INSTANCE.updateLongSightLevel(true); + if (FunctionBuildConfig.isRomaMode) { + controller.setRomaMode(1); + } else { + Objects.requireNonNull(CallerMapUIServiceManager.INSTANCE.getMapUIController()).setLockMode(false); + controller.changeMapVisualAngle(VisualAngleMode.MODE_LONG_SIGHT, null); + } + mSwitchMapModeImage.setImageResource(R.drawable.bus_switch_map_long); + } else { + controller.changeMapVisualAngle(VisualAngleMode.MODE_MEDIUM_SIGHT, null); + mSwitchMapModeImage.setImageResource(R.drawable.bus_switch_map_medium); + } + } + } + }); + + initListener(); + setAutopilotBtnStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()); + ctvAutopilotStatus.setOnClickListener(new OnPreventFastClickListener() { + + @Override + public void onClickImpl(View v) { + restartAutopilot(); + } + }); + + // 模拟 不可自动驾驶,目前场景是刚开机,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.btnAutopilotPingxing).setOnClickListener(view -> + debugAutoPilotStatus(IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING) + ); + + // 模拟 自动驾驶网约车回调数据 + findViewById(R.id.btnAutopilotArrive).setOnClickListener(view -> + debugArrivedStation() + ); + + findViewById(R.id.btnAutopilotRoute).setOnClickListener(view -> debugArrivedRoute()); + + tvArrived.setOnClickListener(view -> { + onArriveStation(); + }); + + 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); + + if (mBadcaseBtn != null) { + CallerDevaToolsManager.INSTANCE.initBadCase(mBadcaseBtn); + CallerAutopilotRecordListenerManager.INSTANCE.addListener(TAG, this); + } + + mAICollectBtn = findViewById(R.id.module_mogo_och_ai_collet_rl); + if (mAICollectBtn != null) { + CallerDevaToolsManager.INSTANCE.initAiCollect(mAICollectBtn); + } + //消息盒子 + viewDriverMsgBoxButton = findViewById(R.id.viewDriverMsgBoxButton); + viewDriverMsgBoxList = findViewById(R.id.viewDriverMsgBoxList); + viewDriverMsgBoxBubble = findViewById(R.id.viewDriverMsgBoxBubble); + viewDriverMsgBoxButton.setClickListener(show -> { + if(show){ + viewDriverMsgBoxList.setVisibility(View.VISIBLE); + viewDriverMsgBoxList.notifyData(); + viewDriverMsgBoxBubble.setVisibility(View.GONE); + viewDriverMsgBoxBubble.isShowData(false); + }else{ + viewDriverMsgBoxList.setVisibility(View.GONE); + viewDriverMsgBoxBubble.setVisibility(View.VISIBLE); + viewDriverMsgBoxBubble.isShowData(true); + } + }); + + smallMapView = findViewById(R.id.smallMapView); + } + + @Override + protected void initViews(Bundle savedInstanceState) { + super.initViews(savedInstanceState); + mapBizView.onCreate(savedInstanceState); + smallMapView.onCreateView(savedInstanceState); + } + + @Override + public void onResume() { + super.onResume(); + mapBizView.onResume(); + smallMapView.onResume(); + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container + , @Nullable Bundle savedInstanceState) { + EventBus.getDefault().register(this); + return super.onCreateView(inflater, container, savedInstanceState); + } + + protected abstract void onArriveStation(); + + private void updateSwitchMapIcon() { + IMogoMapUIController controller = CallerMapUIServiceManager.INSTANCE.getMapUIController(); + if (controller != null) { + if (controller.getCurrentMapVisualAngle().isLongSight()) { + mSwitchMapModeImage.setImageResource(R.drawable.bus_switch_map_long); + } else if (controller.getCurrentMapVisualAngle().isMediumSight()) { + mSwitchMapModeImage.setImageResource(R.drawable.bus_switch_map_medium); + } else { + mSwitchMapModeImage.setImageResource(R.drawable.bus_switch_map_medium); + } + } + } + + private void debugArrivedRoute() { + BDRouteDataTestUtils.converToRouteData(); + } + + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + mapBizView.onSaveInstanceState(outState); + } + + @Override + public void onLowMemory() { + super.onLowMemory(); + mapBizView.onLowMemory(); + } + + @Override + public void onPause() { + super.onPause(); + mapBizView.onPause(); + smallMapView.onPause(); + } + + @Override + public void onDestroyView() { + mapBizView.onDestroy(); + super.onDestroyView(); + CallerAutopilotRecordListenerManager.INSTANCE.removeListener(TAG); + EventBus.getDefault().unregister(this); + } + + @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) { + } + + @Override + public void onBagManagerResult(@NonNull BagManagerOuterClass.BagManager bagManager) { + } + + /** + * 测试到站 + */ + protected abstract void debugArrivedStation(); + + private void initListener() { + MogoMapListenerHandler.Companion.getMogoMapListenerHandler().registerHostMapListener(TAG, this); + } + + /** + * 展示滑动按钮 + * + * @param text 指定的文字 + */ + public void showSlidePanel(String text) { + getActivity().runOnUiThread(() -> { + slidePanelView.setText(text); + slidePanelView.setVisibility(View.VISIBLE); + }); + setArrivedClikable(false); + } + + /** + * 设置进站按钮状态 + * + * @param isClickable + */ + public void setArrivedClikable(boolean isClickable) { + getActivity().runOnUiThread(() -> { + tvArrived.setEnabled(isClickable); + if (isClickable) { + tvArrived.setTextColor(getResources().getColor(R.color.bus_white)); + } else { + tvArrived.setTextColor(getResources().getColor(R.color.bus_arrived_btn_un_clickable_color)); + } + }); + } + + /** + * 隐藏滑动按钮 + */ + public void hideSlidePanel() { + getActivity().runOnUiThread(() -> { + slidePanelView.setVisibility(View.GONE); + }); + } + + public void playDI() { + SoundPoolHelper.getSoundPoolHelper().playSoundWithRedId(getContext(), R.raw.bus_di); + } + + /** + * 改变自动驾驶状态 + * + * @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.bus_autopilot_text_color_disable)); + ctvAutopilotStatusTv.setText(getResources().getString(R.string.bus_loading_autopilot_runnig_tv)); + ctvAutopilotStatusIv.setImageResource(R.drawable.bus_disable_autopilot_icon); +// ctvAutopilotStatus.setSelected(false); + ctvAutopilotStatus.setClickable(true); + ctvAutopilotStatus.setBackground(getContext().getDrawable(R.drawable.bus_autopilot_0_1_status_bg)); + + } else { + ctvAutopilotStatusTv.setTextColor(getResources().getColor(R.color.bus_autopilot_text_color_normal)); + ctvAutopilotStatusIv.setImageResource(R.drawable.bus_ic_autopilot); + if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE == autopilotStatus) { //1可用 +// ctvAutopilotStatus.setSelected(false); + ctvAutopilotStatus.setClickable(true); + ctvAutopilotStatusTv.setText(getResources().getString(R.string.bus_loading_autopilot_runnig_tv)); + ctvAutopilotStatus.setBackground(getContext().getDrawable(R.drawable.bus_autopilot_0_1_status_bg)); + } else if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING == autopilotStatus) { + ctvAutopilotStatusTv.setText(R.string.bus_loading_autopilot_runnig_tv); + ctvAutopilotStatus.setClickable(true); + ctvAutopilotStatus.setBackground(getContext().getDrawable(R.drawable.bus_autopilot_2_status_bg)); +// ctvAutopilotStatus.setSelected(true); + } else if (IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING + == autopilotStatus){ + ctvAutopilotStatusTv.setText(R.string.bus_pingxing_driver); + ctvAutopilotStatus.setClickable(false); + ctvAutopilotStatus.setBackground(getContext().getDrawable(R.drawable.pingxingjiashi)); + } + + } + } + + public void updateAutopilotStatus(int autopilotStatus) { + if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING + == autopilotStatus) {//2 running + ctvAutopilotStatusIv.setImageResource(R.drawable.bus_right_autopilot_icon); + ctvAutopilotStatusTv.setTextColor(getResources().getColor(R.color.bus_autopilot_text_color_normal)); + ctvAutopilotStatusTv.setText(getResources().getString(R.string.bus_loading_autopilot_success_tv)); +// ctvAutopilotStatus.setSelected(false); + ctvAutopilotStatus.setClickable(false); + } else { + ctvAutopilotStatusIv.setImageResource(R.drawable.bus_wrong_autopilot_icon); + ctvAutopilotStatusTv.setTextColor(getResources().getColor(R.color.bus_autopilot_text_color_normal)); + ctvAutopilotStatusTv.setText(getResources().getString(R.string.bus_loading_autopilot_failure_tv)); + ctvAutopilotStatus.setClickable(false); +// ctvAutopilotStatus.setSelected(false); + } + UiThreadHandler.postDelayed(new Runnable() { + @Override + public void run() { + setAutopilotBtnStatus(autopilotStatus); + } + }, 1000); + } + + private void changeAutopilotBtnView(int autopilotStatus, boolean isAnimateRunning) { + if (isAnimateRunning && IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING + != autopilotStatus) { + // 主动开启自动驾驶中,不为2(为0、1)则继续loading + return; + } + if (isAnimateRunning) { + stopAnimAndUpdateBtnStatus(); + } else { + setAutopilotBtnStatus(autopilotStatus); + } + + } + + public void stopAnimAndUpdateBtnStatus() { + stopAutopilotAnimation(); + updateAutopilotStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()); + } + + /** + * 隐藏【自动驾驶】按钮 + */ + public void hideAutopilotBiz() { + getActivity().runOnUiThread(() -> { +// ctvAutopilotStatus.setVisibility(View.GONE); +// slidePanelView.setVisibility(View.GONE); + }); + } + + /** + * 展示【自动驾驶】按钮 + */ + public void showAutopilotBiz() { + getActivity().runOnUiThread(() -> { + ctvAutopilotStatus.setVisibility(View.VISIBLE); + }); + } + + public SlidePanelView.OnSlidePanelMoveToEndListener getSlidePanelOnEndListener() { + return null; + } + + /** + * 获取站点面板view,在{@link #initViews()}时候添加到container中 + * + * @return 站点面板view + */ + public abstract int getStationPanelViewId(); + + /** + * 重新开启自动驾驶 + */ + public abstract void restartAutopilot(); + + /** + * 模拟自动驾驶返回状态 + * + * @param status + */ + public abstract void debugAutoPilotStatus(int status); + + /** + * 开启自动驾驶中间动画 + */ + public void startAutopilotAnimation() { + isAnimateRunning = true; + ctvAutopilotStatusTv.setText(getResources().getString(R.string.bus_loading_autopilot_tv)); + ctvAutopilotStatusTv.setTextColor(getResources().getColor(R.color.bus_autopilot_text_color_normal)); +// ctvAutopilotStatus.setSelected(false); + ctvAutopilotStatus.setClickable(true); + ctvAutopilotStatusIv.setImageResource(R.drawable.bus_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(); + smallMapView.onDestroy(); + MogoMapListenerHandler.Companion.getMogoMapListenerHandler().unregisterHostMapListener(TAG); + } + + @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_bus_test_bar); + lineIdTV = findViewById(R.id.bus_test_bar_current_line_id); + trajMd5TV = findViewById(R.id.bus_test_bar_current_traj_md5); + stopMd5TV = findViewById(R.id.bus_test_bar_current_stop_md5); + trajMd5DPQPTV = findViewById(R.id.bus_test_bar_current_traj_md5_dpqp); + stopMd5DPQPTV = findViewById(R.id.bus_test_bar_current_stop_md5_dpqp); + } + + if (busTestBar.getVisibility() == View.VISIBLE) { + busTestBar.setVisibility(View.GONE); + } else { + BusRoutesResult routesResult = OrderModel.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 updateBusTestBarInfo() { + if (busTestBar != null && busTestBar.getVisibility() == View.VISIBLE) { + BusRoutesResult routesResult = OrderModel.getInstance().getBusRoutesResult(); + lineIdTV.setText("lineId:" + (routesResult == null ? "" : String.valueOf(routesResult.getLineId()))); + trajMd5TV.setText("TMd5:" + (routesResult == null ? "" : routesResult.csvFileMd5)); + stopMd5TV.setText("SMd5:" + (routesResult == null ? "" : routesResult.txtFileMd5)); + trajMd5DPQPTV.setText("TMd5DPQP:" + (routesResult == null ? "" : routesResult.csvFileMd5DPQP)); + stopMd5DPQPTV.setText("SMd5DPQP:" + (routesResult == null ? "" : routesResult.txtFileMd5DPQP)); + } + } + /** + * END + */ +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/fragment/BusFragment.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/fragment/BusFragment.java new file mode 100644 index 0000000000..04308c836b --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/fragment/BusFragment.java @@ -0,0 +1,533 @@ +package com.mogo.och.bus.fragment; + +import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS; + +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.constraintlayout.widget.Group; +import androidx.annotation.Nullable; + +import com.alibaba.android.arouter.launcher.ARouter; +import com.mogo.commons.AbsMogoApplication; +import com.mogo.eagle.core.data.map.CenterLine; +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.CallerMapUIServiceManager; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant; +import com.mogo.eagle.core.utilcode.util.ToastUtils; +import com.mogo.map.marker.IMogoMarker; +import com.mogo.map.marker.MogoMarkerOptions; +import com.mogo.och.bus.R; +import com.mogo.och.bus.constant.BusConst; +import com.mogo.och.bus.net.login.LoginBusImpl; +import com.mogo.och.bus.presenter.BusPresenter; +import com.mogo.och.bus.ui.BusStationCommonItem; +import com.mogo.och.bus.ui.BusSwitchLineActivity; +import com.mogo.och.bus.view.SlidePanelView; +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; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.List; +import java.util.Objects; + + +/** + * 网约车小巴界面 + * + * @author tongchenfei + */ +public class BusFragment extends BaseBusTabFragment + implements SlidePanelView.OnSlidePanelMoveToEndListener, View.OnClickListener { + public static final String TAG = "BusFragment"; + + private TextView mSwitchLine; //切换路线 + private MarqueeTextView mLineName; + private TextView mTaskTime; + private Group groupStationsPanel; + private ConstraintLayout noDataView; + + private BusStationBean startStation = null; + private BusStationBean endStation = null; + private BusStationCommonItem firstStationItem; + private BusStationCommonItem secondStationItem; + private BusStationCommonItem thirdStationItem; + + private LoginService loginService; + + @Override + public String getTagName() { + return "BusFragment"; + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + loginService = (LoginService) ARouter.getInstance().build(OchCommonConst.LOGINSERVICE).navigation(); + if(loginService!=null){ + loginService.registerFragment(this, getPresenter(),new LoginBusImpl()); + } + } + @Override + public void onDestroyView() { + super.onDestroyView(); + loginService.unRegisterFragment(); + loginService = null; + } + + @Override + protected void initViews() { + super.initViews(); + + mSwitchLine = findViewById(R.id.switch_line_btn); + mSwitchLine.setTag(0); + mLineName = findViewById(R.id.module_och_bus_line_name); + + firstStationItem = findViewById(R.id.bus_panel_first_station); + secondStationItem = findViewById(R.id.bus_panel_second_station); + thirdStationItem = findViewById(R.id.bus_panel_third_station); + mTaskTime = findViewById(R.id.bus_task_time_tv); + groupStationsPanel = findViewById(R.id.group_stations_panel); + noDataView = findViewById(R.id.no_line_data_view); + + CallerLogger.INSTANCE.d(M_BUS + TAG, "initView: " + CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()); + // 初始化的时候设置 UI 按钮状态 + showAutopilotBiz(); + + mSwitchLine.setOnClickListener(this); + + mLineName.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + showHideTestBar(); + return false; + } + }); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void changeOverview(EventLogout eventLogout){ + if (eventLogout.getMessgae() == EventLogout.LOGOUT_TYPE){ + CallerLogger.INSTANCE.d(M_BUS + TAG,"changeOverview Event消息去登出"); + mPresenter.logout(); + } + } + + @Override + protected void onArriveStation() { + mPresenter.onAutopilotArriveAtStation(null); + } + + @Override + protected void debugArrivedStation() { + mPresenter.onAutopilotArriveAtStation(null); + } + + @NonNull + @Override + protected BusPresenter createPresenter() { + return new BusPresenter(this); + } + + @Override + public void onResume() { + super.onResume(); + } + + public void hideStationsPanel(){ + groupStationsPanel.setVisibility(View.GONE); + noDataView.setVisibility(View.VISIBLE); + } + + public void showStationsPanel(){ + groupStationsPanel.setVisibility(View.VISIBLE); + noDataView.setVisibility(View.GONE); + } + + public void updateLineEmptyUI(){ + setArrivedClikable(false); + showOrHideSwitchLineBtn(true); + hideStationsPanel(); + hideSlidePanel(); + resetStationBlinkAnim(); + } + + private void resetStationBlinkAnim() { + BlinkAnimationUtil.clearAnimation(firstStationItem.getCircleImageView()); + BlinkAnimationUtil.clearAnimation(secondStationItem.getCircleImageView()); + BlinkAnimationUtil.clearAnimation(thirdStationItem.getCircleImageView()); + } + + public void updateBusTaskStatus(String lineName, String lineTime, + List stationList, + int arrivingOrArrivedIndex, + boolean isArrived){ + + if (getActivity() == null) { + return; + } + + getActivity().runOnUiThread(() -> { + if (stationList == null) { + // 获取小巴数据失败 + return; + } + + showStationsPanel(); + showOrHideSwitchLineBtn(false); + + mLineName.setText(lineName); + mTaskTime.setText(getString(R.string.bus_line_time_tag)+ lineTime); + // 渲染小巴路线数据 + updateBusStationStatus(stationList,arrivingOrArrivedIndex,isArrived); + }); + } + + private void updateBusStationStatus(List stationList, + int arrivingOrArrivedIndex, + boolean isArrived) { + + startStation = stationList.get(0); + endStation = stationList.get(stationList.size() - 1); + + if (arrivingOrArrivedIndex == stationList.size() - 1 && isArrived){ + //切换路线和结束路线按钮切换 + showSlidePanel("单程结束"); + + setOrRemoveMapMaker(false, BusConst.BUS_END_MAP_MAKER, endStation.getLat() + , endStation.getLon(),R.raw.end_marker); + }else if (arrivingOrArrivedIndex == 0 && isArrived){ + + showSlidePanel("滑动出发"); + + setOrRemoveMapMaker(true, BusConst.BUS_START_MAP_MAKER, + startStation.getLat(), startStation.getLon(),R.raw.star_marker); + setOrRemoveMapMaker(true, BusConst.BUS_END_MAP_MAKER, + endStation.getLat(), endStation.getLon(),R.raw.end_marker); + }else{ + if (isArrived){ + // 重置滑动按钮文字 + showSlidePanel("滑动出发"); + } + + setOrRemoveMapMaker(false, BusConst.BUS_START_MAP_MAKER, startStation.getLat() + , startStation.getLon(),R.raw.star_marker); + setOrRemoveMapMaker(true, BusConst.BUS_END_MAP_MAKER, endStation.getLat() + , endStation.getLon(),R.raw.end_marker); + } + + if (stationList.size() > 2){ //只有两个站点 + updateMoreThanTwoStationsUI(stationList,arrivingOrArrivedIndex,isArrived); + }else { + updateTwoStationsUI(stationList,arrivingOrArrivedIndex,isArrived); + } + + updateBusTestBarInfo(); + } + + /** + * 有两个以上站点的路线 + * @param stationList + * @param arrivingOrArrivedIndex + * @param isArrived + */ + private void updateMoreThanTwoStationsUI(List stationList, + int arrivingOrArrivedIndex, + boolean isArrived) { + secondStationItem.setStationTag(""); + secondStationItem.showOrHideStationArrowBg(true); + thirdStationItem.setStationTag(""); + secondStationItem.setVisibility(View.VISIBLE); + thirdStationItem.showOrHideStationArrowBg(false); + + if (arrivingOrArrivedIndex == 0 || arrivingOrArrivedIndex -1 == 0 + || (arrivingOrArrivedIndex -2 == 0 && stationList.size() == 3)){ + firstStationItem.setStationTag(getResources().getString(R.string.bus_station_txt_tag_start)); + }else { + firstStationItem.setStationTag(""); + } + + if (arrivingOrArrivedIndex + 1 == stationList.size() - 1 || arrivingOrArrivedIndex == stationList.size() - 1 + || (arrivingOrArrivedIndex == 0 && arrivingOrArrivedIndex + 2 == stationList.size() - 1)){ //确认是否显示 "终" + thirdStationItem.setStationTag(getResources().getString(R.string.bus_station_txt_tag_end)); + }else { + thirdStationItem.setStationTag(""); + } + + //圆点: 0:灰色 过站 1:绿色 到站或者即将到站 2:蓝色:未到站 + if (arrivingOrArrivedIndex == 0 && isArrived){ + firstStationItem.setStationNameColor(getResources().getColor(R.color.bus_line_station_color_selected)); + secondStationItem.setStationNameColor(getResources().getColor(R.color.bus_arrived_station_name_text_color)); + thirdStationItem.setStationNameColor(getResources().getColor(R.color.bus_arrived_station_name_text_color)); + + firstStationItem.setStationName(stationList.get(0).getName()); + secondStationItem.setStationName(stationList.get(1).getName()); + thirdStationItem.setStationName(stationList.get(2).getName()); + + firstStationItem.setStationPointBg(1); + secondStationItem.setStationPointBg(2); + thirdStationItem.setStationPointBg(2); + + firstStationItem.setStationArrowBg(2); + secondStationItem.setStationArrowBg(2); + + }else if (arrivingOrArrivedIndex == stationList.size() - 1){ + firstStationItem.setStationNameColor(getResources().getColor(R.color.bus_station_tag_txt_un_color)); + secondStationItem.setStationNameColor(getResources().getColor(R.color.bus_station_tag_txt_un_color)); + thirdStationItem.setStationNameColor(getResources().getColor(R.color.bus_line_station_color_selected)); + + firstStationItem.setStationName(stationList.get(arrivingOrArrivedIndex -2).getName()); + secondStationItem.setStationName(stationList.get(arrivingOrArrivedIndex -1).getName()); + thirdStationItem.setStationName(stationList.get(arrivingOrArrivedIndex).getName()); + + firstStationItem.setStationPointBg(0); + secondStationItem.setStationPointBg(0); + thirdStationItem.setStationPointBg(1); + + firstStationItem.setStationArrowBg(0); + if (isArrived){ + secondStationItem.setStationArrowBg(0); + }else { + secondStationItem.setStationArrowBg(1); + } + + }else { + firstStationItem.setStationNameColor(getResources().getColor(R.color.bus_station_tag_txt_un_color)); + secondStationItem.setStationNameColor(getResources().getColor(R.color.bus_line_station_color_selected)); + thirdStationItem.setStationNameColor(getResources().getColor(R.color.bus_arrived_station_name_text_color)); + + firstStationItem.setStationName(stationList.get(arrivingOrArrivedIndex -1).getName()); + secondStationItem.setStationName(stationList.get(arrivingOrArrivedIndex).getName()); + thirdStationItem.setStationName(stationList.get(arrivingOrArrivedIndex + 1).getName()); + + firstStationItem.setStationPointBg(0); + secondStationItem.setStationPointBg(1); + thirdStationItem.setStationPointBg(2); + + secondStationItem.setStationArrowBg(2); + if (isArrived){ + firstStationItem.setStationArrowBg(0); + }else { + firstStationItem.setStationArrowBg(1); + } + } + + } + + /** + * 只有两个站点的路线 + * @param stationList + * @param arrivingOrArrivedIndex + * @param isArrived + */ + private void updateTwoStationsUI(List stationList, + int arrivingOrArrivedIndex, + boolean isArrived) { + + secondStationItem.setVisibility(View.GONE); + secondStationItem.showOrHideStationArrowBg(false); + thirdStationItem.showOrHideStationArrowBg(false); + + firstStationItem.setStationTag(getResources().getString(R.string.bus_station_txt_tag_start)); + thirdStationItem.setStationTag(getResources().getString(R.string.bus_station_txt_tag_end)); + + firstStationItem.setStationName(stationList.get(0).getName()); + thirdStationItem.setStationName(stationList.get(1).getName()); + + //圆点: 0:灰色 过站 1:绿色 到站或者即将到站 2:蓝色:未到站 + if (arrivingOrArrivedIndex == 0 && isArrived){//到站 + firstStationItem.setStationNameColor(getResources().getColor(R.color.bus_line_station_color_selected)); + thirdStationItem.setStationNameColor(getResources().getColor(R.color.bus_arrived_station_name_text_color)); + firstStationItem.setStationPointBg(1); + firstStationItem.setStationArrowBg(2); + thirdStationItem.setStationPointBg(0); + + }else { + firstStationItem.setStationNameColor(getResources().getColor(R.color.bus_station_tag_txt_un_color)); + thirdStationItem.setStationNameColor(getResources().getColor(R.color.bus_line_station_color_selected)); + if (isArrived){ //到终点 + firstStationItem.setStationPointBg(0); + firstStationItem.setStationArrowBg(0); + thirdStationItem.setStationPointBg(1); + + }else { //到终点途中 + firstStationItem.setStationPointBg(0); + firstStationItem.setStationArrowBg(1); + thirdStationItem.setStationPointBg(1); + } + } + } + + private void showOrHideSwitchLineBtn(boolean isShow) { + if (isShow){//显示切换路线 + mSwitchLine.setTag(0); + mSwitchLine.setText(getResources().getString(R.string.bus_switch_line_btn)); + }else {//显示结束路线 + mSwitchLine.setTag(1); + mSwitchLine.setText(getResources().getString(R.string.bus_close_line_btn)); + } + } + + public void hideOchBus() { +// tvNotice.setVisibility(View.GONE); + } + + @Override + public int getStationPanelViewId() { + return R.layout.fragment_och_bus; + } + + @Override + public void restartAutopilot() { + if (!isAnimateRunning) { + mPresenter.restartAutopilot(); + } + } + + @Override + public SlidePanelView.OnSlidePanelMoveToEndListener getSlidePanelOnEndListener() { + return this; + } + + @Override + public void moveToEnd() { + // 开启自动驾驶到下一站 + if (isAnimateRunning){ + stopAutopilotAnimation(); + } + mPresenter.autoDriveToNextStation(); + } + + /** + * 设置自动驾驶可用状态 + */ + public void onAutopilotEnableChange(boolean isEnable) { + if (isEnable) { + showAutopilotBiz(); + } else { + hideAutopilotBiz(); + } + } + + public void clearBusStationsMarkers(){ + CallerLogger.INSTANCE.d(M_BUS + TAG,"clearBusStationsMarkers()"); + if (null != startStation) { + setOrRemoveMapMaker(false, BusConst.BUS_START_MAP_MAKER, startStation.getLat() + , startStation.getLon(),R.raw.star_marker); + } + if (null != endStation) { + setOrRemoveMapMaker(false, BusConst.BUS_END_MAP_MAKER, endStation.getLat() + , endStation.getLon(),R.raw.end_marker); + } + + //清除鹰眼右下角小地图轨迹 + CallerLogger.INSTANCE.d(SceneConstant.M_MAP, "clearBusStationsMarkers --------->"); + smallMapView.clearPolyline(); + } + + /** + * 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 = () -> { + CallerLogger.INSTANCE.d(M_BUS + "setMapMaker= "+Thread.currentThread().getName(), + uuid + "=latitude=" + lat + ",longitude=" + longi); + + MogoMarkerOptions options = new MogoMarkerOptions() + .owner(BusConst.TYPE_MARKER_BUS_ORDER) + .anchor(0.5f, 0.5f) + .set3DMode(true) + .gps(true) + .controlAngle(true) + .icon3DRes(resourceId) + .latitude(lat) + .longitude(longi); + IMogoMarker marker = Objects.requireNonNull(CallerMapUIServiceManager.INSTANCE.getMarkerManager(AbsMogoApplication.getApp())).addMarker(uuid, options); + CenterLine centerLine = CallerMapUIServiceManager.INSTANCE.getMapUIController().getCenterLineInfo( + longi,lat,-1); + if (null != centerLine && marker != null) { // 有可能鹰眼map为空没有角度。判空使用后可能造成maker角度跟道路角度不一致 地图未初始化会返回空 + marker.setRotateAngle(centerLine.getAngle().floatValue()); + } + }; + + OCHThreadPoolManager.getsInstance().execute(setMapMarkerRunnable); + + }else { + Runnable removeMapMarkerRunnable = () -> { + CallerLogger.INSTANCE.d(M_BUS + "RemoveMapMaker="+Thread.currentThread().getName(), + uuid+"=latitude="+lat+",longitude="+longi); + Objects.requireNonNull(CallerMapUIServiceManager.INSTANCE.getMarkerManager(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.bus_switch_line_btn_warning1)); + return; + } + if ((int)mSwitchLine.getTag() == 0){//切换路线 + Intent intent = new Intent(getContext(), BusSwitchLineActivity.class); + startActivity(intent); + }else {//结束任务 + OCHCommitDialog.Builder builder = new OCHCommitDialog.Builder(); + OCHCommitDialog closeLineConfirmDialog = builder + .title(getString(R.string.bus_dialog_title)) + .tips(getString(R.string.bus_dialog_tips)) + .confirmStr(getString(R.string.bus_dialog_confirm)) + .cancelStr(getString(R.string.bus_dialog_cancel)) + .build(getContext()); + closeLineConfirmDialog.setClickListener(new OCHCommitDialog.ClickListener() { + @Override + public void confirm() { + mPresenter.abortTask(); + } + + @Override + public void cancel() { + closeLineConfirmDialog.dismiss(); + } + }); + closeLineConfirmDialog.show(); + } + } + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/model/BusLineModel.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/model/BusLineModel.java new file mode 100644 index 0000000000..723ee5d32a --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/model/BusLineModel.java @@ -0,0 +1,147 @@ +package com.mogo.och.bus.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.SharedPrefs; +import com.mogo.eagle.core.utilcode.util.ToastUtils; +import com.mogo.och.bus.R; +import com.mogo.och.bus.bean.BusQueryLineTaskResponse; +import com.mogo.och.bus.bean.BusQueryLinesResponse; +import com.mogo.och.bus.callback.IBusLinesCallback; +import com.mogo.och.bus.net.OrderServiceManager; +import com.mogo.och.bus.ui.BusSwitchLineActivity; +import com.mogo.och.common.module.biz.network.OchCommonServiceCallback; + +/** + * @author: wangmingjun + * @date: 2022/2/9 + */ +public class BusLineModel { + private static volatile BusLineModel sInstance; + private Context mContext; + private IBusLinesCallback mBusLinesCallback; + public static BusLineModel getInstance() { + if ( sInstance == null ) { + synchronized ( BusLineModel.class ) { + if ( sInstance == null ) { + sInstance = new BusLineModel(); + } + } + } + return sInstance; + } + private BusLineModel() { + + } + public void init() { + mContext = AbsMogoApplication.getApp(); + } + public void setBusLinesCallback(IBusLinesCallback callback){ + mBusLinesCallback = callback; + } + public void queryBusLines(){ + OrderServiceManager.queryBusLines(mContext, new OchCommonServiceCallback() { + @Override + public void onSuccess(BusQueryLinesResponse data) { + if (null == data && mBusLinesCallback != null) { + mBusLinesCallback.onBusLinesChange(null); + return; + } + + if (mBusLinesCallback != null){ + mBusLinesCallback.onBusLinesChange(data); + } + } + + @Override + public void onError() { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort(mContext.getString(R.string.network_error_tip)); + } else { + ToastUtils.showShort(mContext.getString(R.string.request_error_tip)); + } + } + + @Override + public void onFail(int code, String failMsg) { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort("网络异常,请稍后重试"); + }else { + ToastUtils.showShort("查询所有绑定路线失败:"+failMsg); + } + } + }); + } + + /** + * 通过线路id 查询线路排班表 + * @param lineId + * @param position 位置 + */ + public void queryBusLineTasksById(int lineId, int position,boolean autoRefresh){ + OrderServiceManager.queryBusTaskByLineId(mContext, String.valueOf(lineId),new OchCommonServiceCallback() { + @Override + public void onSuccess(BusQueryLineTaskResponse data) { + if (null == data && mBusLinesCallback != null) { + mBusLinesCallback.onBusLineTasks(null,position,autoRefresh); + return; + } + + if (mBusLinesCallback != null){ + mBusLinesCallback.onBusLineTasks(data,position,autoRefresh); + } + } + + @Override + public void onError() { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort(mContext.getString(R.string.network_error_tip)); + } else { + ToastUtils.showShort(mContext.getString(R.string.request_error_tip)); + } + } + + @Override + public void onFail(int code, String failMsg) { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort("网络异常,请稍后重试"); + }else { + ToastUtils.showShort("查询所有绑定路线失败:"+failMsg); + } + } + }); + } + + public void commitSwitchLineId(int taskId,int lineId){ + OrderServiceManager.switchLine(mContext,taskId, new OchCommonServiceCallback() { + @Override + public void onSuccess(BusRoutesResponse o) { + SharedPrefs.getInstance(mContext).putInt(BusSwitchLineActivity.LASTCOMMITLINEID,lineId); + if (mBusLinesCallback != null){ + mBusLinesCallback.onChangeLineIdSuccess(); + } + } + + @Override + public void onError() { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort(mContext.getString(R.string.network_error_tip)); + } else { + ToastUtils.showShort(mContext.getString(R.string.request_error_tip)); + } + } + + @Override + public void onFail(int code, String failMsg) { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort("网络异常,请稍后重试"); + }else { + ToastUtils.showShort("选择任务失败:"+failMsg); + } + } + }); + } + +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/model/OrderModel.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/model/OrderModel.java new file mode 100644 index 0000000000..782e846a97 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/model/OrderModel.java @@ -0,0 +1,1211 @@ +package com.mogo.och.bus.model; + +import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS; +import static com.mogo.och.bus.constant.BusConst.DELAY_10S; +import static com.mogo.och.bus.constant.BusConst.STATION_STATUS_ARRIVING; +import static com.mogo.och.bus.constant.BusConst.STATION_STATUS_STOPPED; + +import android.content.Context; +import android.os.Handler; +import android.os.Message; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.alibaba.android.arouter.launcher.ARouter; +import com.amap.api.maps.model.LatLng; +import com.elegant.network.utils.GsonUtil; +import com.mogo.aicloud.services.socket.IMogoOnMessageListener; +import com.mogo.eagle.core.utilcode.util.CoordinateUtils; +import com.mogo.commons.AbsMogoApplication; +import com.mogo.commons.module.status.IMogoStatusChangedListener; +import com.mogo.commons.module.status.MogoStatusManager; +import com.mogo.commons.module.status.StatusDescriptor; +import com.mogo.eagle.core.data.BaseData; +import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters; +import com.mogo.eagle.core.data.config.FunctionBuildConfig; +import com.mogo.eagle.core.data.map.MogoLocation; +import com.mogo.och.common.module.biz.common.socketmessage.data.SystemMsg; +import com.mogo.och.common.module.biz.constant.OchCommonConst; +import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener; +import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener; +import com.mogo.eagle.core.function.api.autopilot.IMoGoPlanningRottingListener; +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotControlManager; +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager; +import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationGCJ02ListenerManager; +import com.mogo.eagle.core.function.call.autopilot.CallerPlanningRottingListenerManager; +import com.mogo.eagle.core.function.call.telematic.CallerTelematicManager; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.eagle.core.utilcode.util.GsonUtils; +import com.mogo.eagle.core.utilcode.util.NetworkUtils; +import com.mogo.eagle.core.utilcode.util.ToastUtils; +import com.mogo.eagle.core.utilcode.util.UiThreadHandler; +import com.mogo.och.bus.R; +import com.mogo.och.bus.bean.BusRoutePlanningUpdateReqBean; +import com.mogo.och.bus.bean.BusRoutesResult; +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.OrderServiceManager; +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.bean.AppConnectMsg; +import com.mogo.och.common.module.biz.common.socketmessage.OCHSocketMessageManager; +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.AbnormalFactorsLoopManager; +import com.mogo.och.common.module.manager.OCHAdasAbilityManager; +import com.mogo.och.common.module.utils.CoordinateCalculateRouteUtil; +import com.mogo.och.common.module.utils.DateTimeUtil; +import com.mogo.och.common.module.utils.NumberFormatUtil; +import com.mogo.och.common.module.utils.PinYinUtil; +import com.mogo.och.common.module.utils.ToastUtilsOch; +import com.mogo.och.common.module.voice.VoiceManager; +import com.mogo.och.common.module.voice.VoiceNotice; + +import org.jetbrains.annotations.NotNull; + +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 OrderModel { + private final String TAG = OrderModel.class.getSimpleName(); + private int currentLineId = -1; + private int currentTaskId = -1; + private int backgroundCurrentStationIndex = 0;//A->B 此处值是A站点索引 + + private static volatile OrderModel sInstance; + public double mLongitude = 0; + public double mLatitude = 0; + private Context mContext; + private final List stationList = new ArrayList<>(); + private BusRoutesResult busRoutesResult = null; + /** + * 用来表示是否正在开往下一站 + */ + 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 IRefreshBusStationsCallback refreshBusStationsCallback; + private ISlidePannelHideCallback slidePanelHideCallback; + private IBusControllerStatusCallback mControllerStatusCallback; //Model->Presenter:VR mode等 + private IPassengerCallback mPassengerCallback; //乘客核销回调 + private IBusADASStatusCallback mADASStatusCallback; + + List points = new ArrayList<>();//全路径信息 + + private volatile boolean isArrivedStation = false; + + //0: 代表没有启动过 1代表是启动第一次,当>=1 代表是重试 每次到站/路线结束清空置为0 + private volatile int firstStartAutopilot = 0; + + private LoginService loginService; + + private final Handler handler = new Handler(new Handler.Callback() { + @Override + public boolean handleMessage(Message msg) { + if (msg.what == MSG_QUERY_BUS_STATION) { + queryBusRoutes(); + return true; + } + return false; + } + }); + + public static OrderModel getInstance() { + if (sInstance == null) { + synchronized (OrderModel.class) { + if (sInstance == null) { + sInstance = new OrderModel(); + } + } + } + return sInstance; + } + + private OrderModel() { + + } + + public void init() { + mContext = AbsMogoApplication.getApp(); + loginService = (LoginService) ARouter.getInstance().build(OchCommonConst.LOGINSERVICE).navigation(); + // 定位监听 + CallerChassisLocationGCJ02ListenerManager.INSTANCE.addListener(TAG,mMapLocationListener); +// CallerChassisLocationGCJ02ListenerManager.INSTANCE.setListenerHz(TAG,2);//设置5hz, 1s返回一次 + + MogoStatusManager.getInstance().registerStatusChangedListener(TAG, StatusDescriptor.VR_MODE, mMogoStatusChangedListener); + + //自动驾驶路线规划接口 + CallerPlanningRottingListenerManager.INSTANCE.addListener(TAG, moGoAutopilotPlanningListener); + + //开启自驾后 异常信息返回 + OCHAdasAbilityManager.getInstance().setAdasStartFailureCallback(mAdasStartFailureListener); + + OCHSocketMessageManager.INSTANCE.registerSocketMessageListener(//监听运营消息 + OCHSocketMessageManager.msgMonitorType, + mMogoOnMessageListener); + + OCHSocketMessageManager.INSTANCE.registerSocketMessageListener(//监听核销乘客 + OCHSocketMessageManager.msgWriteOffPassengerType, + mWriteOffPassengeOnMessageListener); + + AbnormalFactorsLoopManager.INSTANCE.startLoopAbnormalFactors(mContext); + + //2022.1.28 + // 调用Disposable.dispose() 时候会出现InterruptedException 导致出现崩溃 + // The exception could not be delivered to the consumer because it has already canceled/disposed + // the flow or the excTeption has nowhere to go to begin with + RxJavaPlugins.setErrorHandler(new Consumer() { + @Override + public void accept(Throwable e) { + if (e instanceof UndeliverableException) { + e = e.getCause(); + CallerLogger.INSTANCE.d(M_BUS + TAG, "UndeliverableException"); + } + if ((e instanceof IOException)) {// + // fine, irrelevant network problem or API that throws on cancellation + CallerLogger.INSTANCE.d(M_BUS + TAG, "IOException"); + return; + } + if (e instanceof InterruptedException) { + // fine, some blocking code was interrupted by a dispose call + CallerLogger.INSTANCE.d(M_BUS + TAG, "InterruptedException"); + return; + } + if ((e instanceof NullPointerException) || (e instanceof IllegalArgumentException)) { + // that's likely a bug in the application + CallerLogger.INSTANCE.d(M_BUS + TAG, "NullPointerException or IllegalArgumentException"); + Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e); + return; + } + if (e instanceof IllegalStateException) { + // that's a bug in RxJava or in a custom operator + CallerLogger.INSTANCE.d(M_BUS + TAG, "IllegalStateException"); + Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e); + return; + } + CallerLogger.INSTANCE.d(M_BUS + TAG, "Undeliverable exception"); + } + }); + } + + private final IMogoOnMessageListener mMogoOnMessageListener = + new IMogoOnMessageListener() { + @Override + public Class target() { + return SystemMsg.class; + } + + @Override + public void onMsgReceived(SystemMsg obj) { + if (obj == null){ + CallerLogger.INSTANCE.d(M_BUS + TAG, "onMsgReceived = null"); + return; + } + CallerLogger.INSTANCE.i(M_BUS + TAG,"onMsgReceived = "+obj.getContext()); + List list = obj.getScreenList(); + CallerLogger.INSTANCE.i(M_BUS + TAG,"onMsgReceived = "+GsonUtils.toJson(list)); + + if (list != null && list.contains(1)){ // 1司机端 + OCHSocketMessageManager.INSTANCE.pushAppOperationalMsgBox(DateTimeUtil.getCurrentTimeStamp(), + obj.getContext(),OCHSocketMessageManager.OPERATION_SYSTEM); + } + + if (list != null && list.contains(2)){ //乘客屏 + AppConnectMsg msg = new AppConnectMsg(true,false,obj.getContext()); + CallerTelematicManager.INSTANCE.sendMsgToAllClients(OchCommonConst.BUSINESS_STRING, + GsonUtils.toJson(msg).getBytes()); + } + + } + }; + + private final IMogoOnMessageListener mWriteOffPassengeOnMessageListener = + new IMogoOnMessageListener() { + @Override + public Class target() { + return WriteOffPassenger.class; + } + + @Override + public void onMsgReceived(WriteOffPassenger passenger) { + //进行播报 + CallerLogger.INSTANCE.i(M_BUS + TAG,"passenger = "+ GsonUtil.jsonFromObject(passenger)); + if (passenger != null && passenger.passengerSize == 0) return; + if (mPassengerCallback != null){ + mPassengerCallback.playPassenger(passenger); + } + } + }; + + public void setAdasStatusCallback(IBusADASStatusCallback callback){ + this.mADASStatusCallback = callback; + } + + public void setRefreshBusStationsCallback(IRefreshBusStationsCallback callback){ + this.refreshBusStationsCallback = callback; + } + + public void setPassengerCallback(IPassengerCallback callback) { + this.mPassengerCallback = callback; + } + + public void setSlidePanelHideCallback(ISlidePannelHideCallback callback) { + this.slidePanelHideCallback = callback; + } + + public void setControllerStatusCallback(IBusControllerStatusCallback callback) { + this.mControllerStatusCallback = callback; + } + + private final IMoGoPlanningRottingListener moGoAutopilotPlanningListener = new IMoGoPlanningRottingListener() { + + @Override + public void onAutopilotRotting(MessagePad.GlobalPathResp routeList) { + if (null != routeList && routeList.getWayPointsList().size() > 0) { + points.clear(); + points.addAll(coordinateConverterWgsToGcjList(mContext, routeList.getWayPointsList())); + } + } + + }; + + public static List coordinateConverterWgsToGcjList(Context mContext, List mogoLatLngList) { + List points = new ArrayList<>(); + for (MessagePad.Location m : mogoLatLngList) { + LatLng mogoLatLng = CoordinateCalculateRouteUtil.coordinateConverterWgsToGcj(mContext, m); + BusRoutePlanningUpdateReqBean.Result result = new BusRoutePlanningUpdateReqBean.Result(); + result.latitude = mogoLatLng.latitude; + result.longitude = mogoLatLng.longitude; + points.add(result); + } + return points; + } + + public void debugUpdateOrderRoute(List list) { + points.clear(); + points.addAll(coordinateConverterWgsToGcjList(mContext, list)); + } + + public void release() { + + MogoStatusManager.getInstance().unregisterStatusChangedListener(TAG, StatusDescriptor.VR_MODE, mMogoStatusChangedListener); + + // 注销定位监听 + CallerChassisLocationGCJ02ListenerManager.INSTANCE.removeListener(TAG); + + //自动驾驶路线规划接口 + CallerPlanningRottingListenerManager.INSTANCE.removeListener(moGoAutopilotPlanningListener); + loginService = null; + + OCHAdasAbilityManager.getInstance().setAdasStartFailureCallback(null); + + OCHSocketMessageManager.INSTANCE.releaseSocketMessageListener( + OCHSocketMessageManager.msgMonitorType); + OCHSocketMessageManager.INSTANCE.releaseSocketMessageListener( + OCHSocketMessageManager.msgWriteOffPassengerType); + + AbnormalFactorsLoopManager.INSTANCE.stopLoopAbnormalFactors(); + } + + private Object readResolve() { + // 阻止反序列化,必须实现 Serializable 接口 + return sInstance; + } + + private final IMogoStatusChangedListener mMogoStatusChangedListener = new IMogoStatusChangedListener() { + // VR mode变更回调 + @Override + public void onStatusChanged(StatusDescriptor descriptor, boolean isTrue) { + if (StatusDescriptor.VR_MODE == descriptor) { + if (mControllerStatusCallback != null) { + mControllerStatusCallback.onVRModeChanged(isTrue); + } + } + } + }; + + private final OchAdasStartFailureCallback mAdasStartFailureListener = new OchAdasStartFailureCallback() { + @Override + public void onStartAutopilotFailure(@NotNull String startFailedCode, @NonNull String startFailedMessage) { + BusAnalyticsManager.getInstance().triggerStartAutopilotFailureEventByAdas(startFailedCode, startFailedMessage); + if (mADASStatusCallback != null && !FunctionBuildConfig.isDemoMode){ + CallerLogger.INSTANCE.e( M_BUS + TAG, "mAdasStartFailureListener = "+startFailedMessage ); + mADASStatusCallback.onStartAdasFailure(); + } + } + }; + + // 自车定位 + private final IMoGoChassisLocationGCJ02Listener mMapLocationListener = new IMoGoChassisLocationGCJ02Listener() { + + @Override + public void onChassisLocationGCJ02(@Nullable MogoLocation mogoLocation) { + if (null == mogoLocation) return; + mLongitude = mogoLocation.getLongitude(); + mLatitude = mogoLocation.getLatitude(); + if (mControllerStatusCallback != null) { + mControllerStatusCallback.onCarLocationChanged(mogoLocation); + } + + //是否到站的围栏判断 离站状态并且自动驾驶还未触发到站 + if (isGoingToNextStation && !isArrivedStation) { + judgeArrivedStation(mogoLocation); + } + } + }; + + //根据围栏判断,是否到达站点 + private void judgeArrivedStation(MogoLocation location) { + + if (backgroundCurrentStationIndex + 1 > stationList.size() - 1) { + CallerLogger.INSTANCE.e(M_BUS + TAG, "到站数组越界"); + return; + } + BusStationBean upcomingStation = stationList.get(backgroundCurrentStationIndex + 1); + + double startLon = upcomingStation.getGcjLon(); + double startLat = upcomingStation.getGcjLat(); + double distance = CoordinateUtils.calculateLineDistance( + startLon, startLat, + location.getLongitude(), location.getLatitude()); + + if (distance <= BusConst.ARRIVE_AT_END_STATION_DISTANCE) { + CallerLogger.INSTANCE.d(M_BUS + TAG, "行程日志-judgeArrivedStation() distance = " + distance + + " to " + upcomingStation.getName()); + onArriveAt(null); //无自动驾驶到站信息传null + return; + } + } + + /** + * 查询小巴路线 + */ + public void queryBusRoutes() { + CallerLogger.INSTANCE.d(M_BUS + TAG, "查询小巴路线"); + OrderServiceManager.queryBusRoutes(mContext, new OchCommonServiceCallback() { + @Override + public void onSuccess(BusRoutesResponse data) { + if (data == null + || data.getResult() == null + || data.getResult().getSites() == null + || data.getResult().getSites().isEmpty()) { + //当为空时,显示无绑定路线图 + CallerLogger.INSTANCE.d(M_BUS + TAG, "获取到小巴路线数据:空 "); + if (refreshBusStationsCallback != null) { + refreshBusStationsCallback.updateEmptyUi(); + } + clearAutopilotControlParameters(); + closeBeautificationMode(); + clearStartAutopilotTag(); + removeTipRunnables(); + return; + } + CallerLogger.INSTANCE.d(M_BUS + TAG, "获取到小巴路线数据: " + data); + updateBusStatus(data.getResult()); + } + + + @Override + public void onError() { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort(mContext.getString(R.string.network_error_tip)); + } else { + ToastUtils.showShort(mContext.getString(R.string.request_error_tip)); + } + } + + @Override + public void onFail(int code, String failMsg) { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort("网络异常,请稍后重试"); + }else { + ToastUtils.showShort(failMsg); + } + } + }); + + } + + /** + * 更新正在运行的任务UI + * + * @param stations + */ + private void updateBusTaskStatus(List stations) { + + int arrivingOrArrivedStationIndex = 0;//已经到站或者即将到站的索引呢 + + for (int i = 0; i < stations.size(); i++) { + BusStationBean station = stations.get(i); + + if (i == 0) { // 首发站 显示在最上面 + if (station.getDrivingStatus() == STATION_STATUS_STOPPED + && !station.isLeaving()) { //到达第一站 + arrivingOrArrivedStationIndex = i; + break; + } + } else { + BusStationBean preStation = stations.get(i - 1); + if ((station.getDrivingStatus() == STATION_STATUS_STOPPED && !station.isLeaving()) + || (station.getDrivingStatus() == STATION_STATUS_ARRIVING + && preStation.isLeaving())) { + //到站未离开 | 即将到站 显示在最中间 + arrivingOrArrivedStationIndex = i; + break; + } + } + } + + BusStationBean arrivingOrArrivedStation = stations.get(arrivingOrArrivedStationIndex); + + String lineTime = DateTimeUtil.formatLongToString( + busRoutesResult.getTaskTime(), + DateTimeUtil.HH_mm); + + if (arrivingOrArrivedStationIndex == 0 || + arrivingOrArrivedStation.getDrivingStatus() == STATION_STATUS_STOPPED + && !arrivingOrArrivedStation.isLeaving()) { + if (refreshBusStationsCallback != null) { + refreshBusStationsCallback.updateBusTaskStatus(busRoutesResult.getName(), lineTime, + stationList, arrivingOrArrivedStationIndex, true); + } + clearAutopilotControlParameters(); + } else { + if (refreshBusStationsCallback != null) { + refreshBusStationsCallback.updateBusTaskStatus(busRoutesResult.getName(), lineTime, + stationList, arrivingOrArrivedStationIndex, false); + } + updateAutopilotControlParameters(); + } + } + + /** + * 重置路线站点状态--结束路线,当前路线恢复到始发站 + */ + public void abortTask() { + CallerLogger.INSTANCE.d(M_BUS + TAG, "结束当前路线abortTask"); + OrderServiceManager.abortTask(mContext, currentTaskId + , new OchCommonServiceCallback() { + @Override + public void onSuccess(BaseData o) { + CallerLogger.INSTANCE.d(M_BUS + TAG, "abortTask success: " + o); + if (o.code == 0) { // 重置成功 + endOrAbortTaskSuccess(); + clearBusStationDatas(); + queryBusRoutes(); + removeTipRunnables(); + // startOrStopQueryPassengerWriteOff(false); + } + } + + @Override + public void onError() { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort(mContext.getString(R.string.network_error_tip)); + } else { + ToastUtils.showShort(mContext.getString(R.string.request_error_tip)); + } + } + + @Override + public void onFail(int code, String failMsg) { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort("网络异常,请稍后重试"); + }else { + ToastUtils.showShort(failMsg); + } + } + }); + + } + + /** + * 中断或者正常结束任务后的处理 + */ + private void endOrAbortTaskSuccess() { + + isGoingToNextStation = false; + backgroundCurrentStationIndex = 0; + + if (busRoutesResult != null) { + BusSendTripInfoManager.INSTANCE.sendBusTripInfo(BusSendTripInfoManager.END_TRIP + , busRoutesResult.getName() + , "" + , "" + , false); + } + } + + /** + * 离站上报成功后渲染站点 + * 服务端返回的OchBusRoutesResult逻辑, 离开站为当前站, 到达下一站后才会将下一站置为当前站, + * 车机端展示是离开当前站,下一站设置为当前站, 所以服务端数据回来要做处理,不能直接渲染 + */ + private void leaveStationSuccess(int leaveIndex, String leaveStation, String nextStation) { + + onStartAutopilot(leaveIndex); + + leaveTTSTips(nextStation); + + sendStartStationToClient(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() + == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) { + startAutopilot(false, leaveIndex); + } else { + firstStartAutopilot = 0; + } + } + + /** + * 开启自动驾驶 + * + * @param isRestart + */ + private void startAutopilot(boolean isRestart, int leaveIndex) { + + if (!FunctionBuildConfig.isDemoMode && !OCHAdasAbilityManager.getInstance().getAutopilotAbilityStatus()) { + ToastUtils.showLong(OCHAdasAbilityManager.getInstance().getAutopilotUnAbilityReason() + + ", 请稍候重试"); + triggerUnableStartAPReasonEvent(); + return; + } + + firstStartAutopilot++; + + triggerStartServiceEvent(isRestart, false); + + AutopilotControlParameters parameters = initAutopilotControlParameters(leaveIndex); + if (null == parameters) { + CallerLogger.INSTANCE.e(M_BUS + TAG, "行程日志-AutopilotControlParameters is empty."); + return; + } + + CallerAutoPilotControlManager.INSTANCE.startAutoPilot(parameters); + + CallerLogger.INSTANCE.d(M_BUS + TAG, "行程日志-开启自动驾驶====" + GsonUtil.jsonFromObject(parameters) + + " startLatLon=" + parameters.startName + ",endLatLon=" + parameters.endName + + "isRestart = " + isRestart); + + if (mControllerStatusCallback != null) { + mControllerStatusCallback.startOpenAutopilot(); + } + } + + /** + * 到站后重置站点状态 + */ + private void arriveSiteStation() { + if ( backgroundCurrentStationIndex +1 > stationList.size() - 1 ) { //到站短时间内调用多次 + CallerLogger.INSTANCE.e( M_BUS + TAG, "数组越界" ); + return; + } + 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); + + OrderServiceManager.arriveSiteStation(mContext, + stationList.get(arrivedStationIndex).getSeq(), + stationList.get(arrivedStationIndex).getSiteId(), + currentTaskId, + new OchCommonServiceCallback() { + @Override + public void onSuccess(BaseData o) { + CallerLogger.INSTANCE.d(M_BUS + TAG, "行程日志-arriveSiteStation success"); + if (o != null && o.code == 0){ + queryBusRoutes(); + isArrivedStation = true; + isGoingToNextStation = false; + arriveStationSuccess(arrivedStationIndex, departureStopName, arriveStation); + } + //5s轮询核销乘客 +// startOrStopQueryPassengerWriteOff(true); + } + + @Override + public void onError() { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort(mContext.getString(R.string.network_error_tip)); + } else { + ToastUtils.showShort(mContext.getString(R.string.request_error_tip)); + } + } + + @Override + public void onFail(int code, String failMsg) { + if (ToastUtilsOch.isCustomFastClick(5000)) { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort("网络异常,请稍后重试"); + } else { + if (isArrivedStation) return; + ToastUtils.showShort(failMsg); + } + } + } + }); + } + + 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); + } + + VoiceManager.INSTANCE.arrivedStation(arriveStation); + + sendArrivedStationToClient(arriveStation); + } + + private void sendArrivedStationToClient(String arriveStation) { + AppConnectMsg arrivedMsg = new AppConnectMsg(false,true,String.format(mContext + .getString(R.string.bus_arrived_station_tip), + arriveStation)); + CallerTelematicManager.INSTANCE.sendMsgToAllClients(OchCommonConst.BUSINESS_STRING, + GsonUtils.toJson(arrivedMsg).getBytes()); + } + + private void sendStartStationToClient(String nextStation) { + AppConnectMsg arrivedMsg = new AppConnectMsg(false,true,String.format(mContext + .getString(R.string.bus_leave_station_tip), + nextStation)); + UiThreadHandler.postDelayed(()->{ + CallerTelematicManager.INSTANCE.sendMsgToAllClients(OchCommonConst.BUSINESS_STRING, + GsonUtils.toJson(arrivedMsg).getBytes()); + },DELAY_10S); + } + + private void sendEndTaskToClient() { + AppConnectMsg arrivedMsg = new AppConnectMsg(false,true,mContext + .getString(R.string.bus_end_task_tip)); + + CallerTelematicManager.INSTANCE.sendMsgToAllClients(OchCommonConst.BUSINESS_STRING, + GsonUtils.toJson(arrivedMsg).getBytes()); + } + + public void sendWriteOffNumToClient(String msg){ + AppConnectMsg arrivedMsg = new AppConnectMsg(false,true,msg); + + CallerTelematicManager.INSTANCE.sendMsgToAllClients(OchCommonConst.BUSINESS_STRING, + GsonUtils.toJson(arrivedMsg).getBytes()); + } + + /** + * 离站上报 + */ + public void leaveStation() { + CallerLogger.INSTANCE.d(M_BUS + TAG, "leaveStation-backgroundCurrentStationIndex = " + backgroundCurrentStationIndex); + String nextStationName = ""; + if (backgroundCurrentStationIndex < stationList.size() - 1) { + nextStationName = stationList.get(backgroundCurrentStationIndex + 1).getName(); + } + final String currentStationName = stationList.get(backgroundCurrentStationIndex).getName(); + String finalNextStationName = nextStationName; + OrderServiceManager.leaveStation(mContext, + stationList.get(backgroundCurrentStationIndex).getSeq(), + stationList.get(backgroundCurrentStationIndex).getSiteId(), + currentTaskId, + new OchCommonServiceCallback() { + @Override + public void onSuccess(BaseData o) { + isArrivedStation = false; + CallerLogger.INSTANCE.d(M_BUS + TAG, "行程日志-离站成功开往下一站===="); + //需要更改当前站和下一站的状态 然后渲染 + //startOrStopQueryPassengerWriteOff(false); + queryBusRoutes(); + leaveStationSuccess(backgroundCurrentStationIndex, currentStationName, finalNextStationName); + } + + + @Override + public void onError() { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort(mContext.getString(R.string.network_error_tip)); + } else { + ToastUtils.showShort(mContext.getString(R.string.request_error_tip)); + } + } + + @Override + public void onFail(int code, String failMsg) { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort("网络异常,请稍后重试"); + } else { + ToastUtils.showShort("离站上报失败:" + failMsg); + } + } + }); + } + + //车站10s后播报 + private void leaveTTSTips(String nextStation) { + UiThreadHandler.postDelayed(new Runnable() { + @Override + public void run() {//延迟10s播报 + VoiceManager.INSTANCE.leaveStation(nextStation); + } + },DELAY_10S); + + } + + /** + * 关闭美化模式 + */ + public void closeBeautificationMode() { + if (FunctionBuildConfig.isDemoMode) {//收车结束美化 + FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData = false; //是否强制绘制引导线 + CallerAutoPilotControlManager.INSTANCE.setIgnoreConditionDraw(false);// 同步给乘客屏 + CallerAutoPilotControlManager.INSTANCE.setIPCDemoMode(false);//是否自动启动自驾 + CallerLogger.INSTANCE.d(M_BUS + TAG, "美化模式-ignore:置为false"); + } + } + + /** + * 开启自动驾驶到下一站 + */ + public void autoDriveToNextStation() { + if (backgroundCurrentStationIndex >= stationList.size() - 1) { + // 当前站是最后一站,结束当前行程 + travelOver(); + return; + } + leaveStation(); + } + + /** + * 渲染站点信息 + * 服务端返回的OchBusRoutesResult逻辑, 离开站为当前站, 到达下一站后才会将下一站置为当前站, + * 车机端展示 三站: 中间为即将到到达或者刚到达的站 + * + * @param result + */ + private void updateBusStatus(BusRoutesResult result) { + if (result == null) return; + busRoutesResult = result; + List site = result.getSites(); + currentTaskId = result.getTaskId(); + currentLineId = result.getLineId(); + stationList.clear(); + stationList.addAll(site); + + for (int i = 0; i < stationList.size(); i++) { + BusStationBean s = stationList.get(i); + + CallerLogger.INSTANCE.d(M_BUS + "updateBusStationsStatus--", + "Index=" + i + " ,name = " + s.getName() + " ," + s.isLeaving() + "," + s.getDrivingStatus()); + + // 是否正在开往下一站 + if (s.isLeaving()) { + isGoingToNextStation = true; + } + // 当前站点信息 + if (s.getDrivingStatus() == STATION_STATUS_STOPPED) { + backgroundCurrentStationIndex = i; + break; + } + } + + 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); + } + + //任务选择后首发前给司机提示任务 + if (busRoutesResult != null){ + beforeTaskTips(); + } +// startOrStopQueryPassengerWriteOff(true); + }else { + removeTipRunnables(); + } + + BusStationBean currentStation = stationList.get(backgroundCurrentStationIndex); + + CallerLogger.INSTANCE.d(M_BUS + TAG, + "行程日志-STATION_STATUS_STOPPED-backgroundCurrentStationIndex=" + + backgroundCurrentStationIndex + + " isLeaving()=" + currentStation.isLeaving()); + + // 美化是否开始 + if (FunctionBuildConfig.isDemoMode && (backgroundCurrentStationIndex >= 0 + && backgroundCurrentStationIndex <= stationList.size() - 1)) {//行驶过程中设置美化 + if (stationList.get(backgroundCurrentStationIndex).isLeaving()) { + startBeautificationMode(); + CallerLogger.INSTANCE.d(M_BUS + TAG, "美化模式-ignore:置为true(每次滑动出发)"); + } else if (backgroundCurrentStationIndex > 0 && backgroundCurrentStationIndex < stationList.size() - 1) { + //美化模式下 中间站点到站 引导线要一直绘制,所以此处不出强制绘制不传false + CallerAutoPilotControlManager.INSTANCE.setIPCDemoMode(false); + CallerLogger.INSTANCE.d(M_BUS + TAG, "美化模式-ignore:false(到达中间站)"); + clearStartAutopilotTag(); + } else { + closeBeautificationMode(); + clearStartAutopilotTag(); + } + } + + + if (currentStation.isLeaving() && slidePanelHideCallback != null) { + slidePanelHideCallback.hideSlidePanel(); + } + + //更新bus路线面板 + updateBusTaskStatus(stationList); + + //需放在currentStationIndex赋值之后 + BusTrajectoryManager.getInstance().syncTrajectoryInfo(); + } + + private void beforeTaskTips() { + if (busRoutesResult == null) return; + + removeTipRunnables(); + + long taskTime = busRoutesResult.getTaskTime(); + long tip3Time = taskTime- 3*60*1000 - DateTimeUtil.getCurrentTimeStamp(); // 首站离开前3分钟提示 + long tip1Time = taskTime-60*1000 - DateTimeUtil.getCurrentTimeStamp(); // 首站离开前1分钟提示 + + if (tip3Time > 0){ + UiThreadHandler.postDelayed(tip3Runnable,tip3Time); + } + + if (tip1Time > 0){ + UiThreadHandler.postDelayed(tip1Runnable,tip1Time); + } + } + + Runnable tip3Runnable = new Runnable() { + @Override + public void run() { + + if (backgroundCurrentStationIndex == 0 && stationList.get(0).getDrivingStatus() == STATION_STATUS_STOPPED + && !stationList.get(0).isLeaving()){ + tipStartTask("3"); + }else { + removeTipRunnables(); + } + } + }; + + private void tipStartTask(String s) { + String tips = String.format(mContext + .getString(R.string.bus_before_tips_s), s); + //展示在运营消息 + OCHSocketMessageManager.INSTANCE.pushAppOperationalMsgBox( + DateTimeUtil.getCurrentTimeStamp(), + tips,OCHSocketMessageManager.OPERATION_SYSTEM); + //语音提示 + VoiceNotice.showNotice(tips); + } + + Runnable tip1Runnable = new Runnable() { + @Override + public void run() { + if (backgroundCurrentStationIndex == 0 && stationList != null && + stationList.get(0).getDrivingStatus() == STATION_STATUS_STOPPED + && !stationList.get(0).isLeaving()){ + tipStartTask("1"); + }else { + removeTipRunnables(); + } + } + }; + + public void removeTipRunnables(){ + if (tip3Runnable != null){ + UiThreadHandler.removeCallbacks(tip3Runnable); + } + if (tip1Runnable != null){ + UiThreadHandler.removeCallbacks(tip1Runnable); + } + } + + private void clearStartAutopilotTag() { + firstStartAutopilot = 0; + } + + private void startBeautificationMode() { + FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData = true; + CallerAutoPilotControlManager.INSTANCE.setIgnoreConditionDraw(true); + CallerAutoPilotControlManager.INSTANCE.setIPCDemoMode(true); + } + + public void clearBusStationDatas() { + if (refreshBusStationsCallback != null) { + refreshBusStationsCallback.clearBusStationsMarkers(); + } + } + + /** + * 延时查询站点信心 + */ + private void queryBusStationDelay() { + handler.sendEmptyMessageDelayed(MSG_QUERY_BUS_STATION, QUERY_BUS_STATION_DELAY); + } + + /** + * 在踩刹车、控制方向盘等操作后,会停止自动驾驶,重启自动驾驶的话相当于重新设置自动驾驶目的地 + */ + public void restartAutopilot() { + CallerLogger.INSTANCE.d(M_BUS + TAG, "行程日志-重启自动驾驶===" + isGoingToNextStation); + //只去启动自动驾驶,不再去上报离站 + startAutopilot(firstStartAutopilot >= 1, -1); + } + + public boolean isRestartAutopilot() { + return firstStartAutopilot > 1; + } + + /** + * 行程结束 + */ + 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, "单程结束===="); + CallerAutoPilotControlManager.INSTANCE.cancelAutoPilot(); + + endTask(); + } + + /** + * task正常结束 + */ + private void endTask() { + CallerLogger.INSTANCE.d(M_BUS + TAG, "任务正常走完endTask()"); + OrderServiceManager.endTask(mContext, currentTaskId + , new OchCommonServiceCallback() { + @Override + public void onSuccess(BaseData o) { + CallerLogger.INSTANCE.d(M_BUS + TAG, "endTask success: " + o); + if (o.code == 0) { + endOrAbortTaskSuccess(); + clearBusStationDatas(); + queryBusRoutes();// 重新获取任务 + removeTipRunnables(); +// startOrStopQueryPassengerWriteOff(false); + VoiceManager.INSTANCE.endOrder(); + sendEndTaskToClient(); + } + } + + @Override + public void onError() { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort(mContext.getString(R.string.network_error_tip)); + } else { + ToastUtils.showShort(mContext.getString(R.string.request_error_tip)); + } + } + + @Override + public void onFail(int code, String failMsg) { + if (!NetworkUtils.isConnected(mContext)) { + ToastUtils.showShort("网络异常,请稍后重试"); + }else { + ToastUtils.showShort(failMsg); + } + } + }); + } + + /** + * 到站 + * + * @param data + */ + public void onArriveAt(MessagePad.ArrivalNotification data) { + if (backgroundCurrentStationIndex + 1 > stationList.size() - 1) { + CallerLogger.INSTANCE.e(M_BUS + TAG, "行程日志-到站异常,取消后续操作结束"); + return; + } + + //MAP 280 每隔100ms左右返回一次到站, 导致在到达中间站后再次滑动出发后会有时间差,收到一次到站,出现问题 + //此处比对 自驾告诉的到站站点坐标和本地应到站站点坐标, 一致时才能到站 + if (data != null && data.getEndLocation() != null) { + + String latitude = NumberFormatUtil.cutOutNumber(data.getEndLocation().getLatitude(), 5); //wgs + String longitude = NumberFormatUtil.cutOutNumber(data.getEndLocation().getLongitude(), 5); + + int arrivedStationIndex = backgroundCurrentStationIndex + 1; + BusStationBean arriveStation = stationList.get(arrivedStationIndex); + String arriveLat = NumberFormatUtil.cutOutNumber(arriveStation.getLat(), 5); + String arriveLon = NumberFormatUtil.cutOutNumber(arriveStation.getLon(), 5); + + if (!latitude.equals(arriveLat) || !longitude.equals(arriveLon)) { + CallerLogger.INSTANCE.e(M_BUS + TAG, "行程日志-到站拦截,到站坐标不一致"); + return; + } + } + + if (isArrivedStation) return; + + CallerLogger.INSTANCE.d(M_BUS + TAG, "行程日志-当前==backgroundCurrentStationIndex=" + + backgroundCurrentStationIndex); + + arriveSiteStation(); + } + + public boolean isGoingToNextStation() { + return isGoingToNextStation; + } + + // 登出 + public void logout() { + loginService.loginOut(mLatitude, mLongitude); + } + + public void triggerStartServiceEvent(boolean isRestart, boolean send) { + if (stationList == null || backgroundCurrentStationIndex >= stationList.size() - 1) { + return; + } + BusStationBean currentStation = stationList.get(backgroundCurrentStationIndex); + BusStationBean nextStation = stationList.get(backgroundCurrentStationIndex + 1); + BusAnalyticsManager.getInstance().triggerStartAutopilotEvent(isRestart, send, + 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; + } + + public int getCurrentStationIndex() { + return backgroundCurrentStationIndex; + } + + /** + * 将业务订单信息保存,鹰眼可取用 + */ + private void updateAutopilotControlParameters() { + + AutopilotControlParameters parameters = initAutopilotControlParameters(-1); + if (null == parameters) { + CallerLogger.INSTANCE.e(M_BUS + TAG, "AutopilotControlParameters is empty."); + return; + } + CallerLogger.INSTANCE.d(M_BUS + TAG, "AutopilotControlParameters is update."); + CallerAutoPilotStatusListenerManager.INSTANCE.updateAutopilotControlParameters(parameters); + } + + private void clearAutopilotControlParameters() { + CallerLogger.INSTANCE.d(M_BUS + TAG, "AutopilotControlParameters is clear."); + CallerAutoPilotStatusListenerManager.INSTANCE.updateAutopilotControlParameters(null); + } + + private AutopilotControlParameters initAutopilotControlParameters(int leaveIndex) { + BusStationBean currentStation = null; + BusStationBean nextStation = null; + + if (leaveIndex < 0) { + if (backgroundCurrentStationIndex + 1 > stationList.size() - 1 || !isGoingToNextStation) { + CallerLogger.INSTANCE.e(M_BUS + TAG, "行程日志-mismatch condition1."); + return null; + } + currentStation = stationList.get(backgroundCurrentStationIndex); + nextStation = stationList.get(backgroundCurrentStationIndex + 1); + } else { + if (leaveIndex + 1 > stationList.size() - 1 || !isGoingToNextStation) { + CallerLogger.INSTANCE.e(M_BUS + TAG, "行程日志-mismatch condition2."); + return null; + } + currentStation = stationList.get(leaveIndex); + nextStation = stationList.get(leaveIndex + 1); + } + + AutopilotControlParameters parameters = new AutopilotControlParameters(); + parameters.routeID = busRoutesResult.getLineId(); + parameters.routeName = busRoutesResult.getName(); + parameters.startName = PinYinUtil.getPinYinHeadChar(currentStation.getName()); + parameters.endName = PinYinUtil.getPinYinHeadChar(nextStation.getName()); + parameters.startLatLon = new AutopilotControlParameters + .AutoPilotLonLat(currentStation.getLat(), currentStation.getLon()); + parameters.endLatLon = new AutopilotControlParameters + .AutoPilotLonLat(nextStation.getLat(), nextStation.getLon()); + parameters.vehicleType = VEHICLE_TYPE; + if (parameters.autoPilotLine == null) { + parameters.autoPilotLine = new AutopilotControlParameters.AutoPilotLine( + busRoutesResult.getLineId(), + busRoutesResult.csvFileUrl, busRoutesResult.csvFileMd5, + busRoutesResult.txtFileUrl, busRoutesResult.txtFileMd5, + busRoutesResult.contrailSaveTime, busRoutesResult.carModel, + busRoutesResult.csvFileUrlDPQP, busRoutesResult.csvFileMd5DPQP, + busRoutesResult.txtFileUrlDPQP, busRoutesResult.txtFileMd5DPQP, + busRoutesResult.contrailSaveTimeDPQP); + } + + return parameters; + } + + //接驳车不需要实现 + public void startOrStopOrderLoop(boolean start) { + + } + // //接驳车不需要实现 + public void runCarHeartbeat() { + + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/net/IBascApiService.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/net/IBascApiService.java new file mode 100644 index 0000000000..14820d0c07 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/net/IBascApiService.java @@ -0,0 +1,127 @@ +package com.mogo.och.bus.net; +import com.mogo.eagle.core.data.BaseData; +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.BusQueryLineStationsRequest; +import com.mogo.och.bus.bean.QueryLeaveAwayPassengersRequest; +import com.mogo.och.bus.bean.QueryLeaveAwayPassengersResponse; +import com.mogo.och.bus.bean.BusResetDrivingLineRequest; +import com.mogo.och.bus.bean.BusUpdateSiteStatusRequest; + +import io.reactivex.Observable; +import retrofit2.http.Body; +import retrofit2.http.GET; +import retrofit2.http.Header; +import retrofit2.http.Headers; +import retrofit2.http.POST; +import retrofit2.http.Query; + +/** + * 小巴车相关接口 + * + * @author tongchenfei + *

+ * wiki: http://wiki.zhidaohulian.com/pages/viewpage.action?pageId=48970072 + */ +public interface IBascApiService { + /** + * 查询当前运行任务 + * + * @param request 请求参数 + * @return 接口返回数据 + */ + @Headers( {"Content-Type:application/json;charset=UTF-8"} ) + @POST( "/och-shuttle-cabin/api/business/v1/driver/lineDataWithDriver/query" ) + Observable queryBusRoutes(@Header ("appId") String appId, @Header("ticket") String ticket, @Body BusQueryLineStationsRequest request); + + /** + * @param request 请求参数{"destLine":1,"sn":"F803EB2046PZD00229"} 这个接口是重置bus线路的, 不是重置线路中站点的 + * @return 返回值是重置后的车站列表 + * 开始路线 + */ + @Headers( {"Content-Type:application/json;charset=UTF-8"} ) + @POST( "/och-shuttle-cabin/api/flow/v1/driver/startTask" ) + Observable switchLine(@Header ("appId") String appId, @Header("ticket") String ticket, @Body BusResetDrivingLineRequest request); + + /** + * 离站,通知服务器 + * @param request + * @return + */ + @Headers({"Content-Type:application/json;charset=UTF-8"}) + @POST("/och-shuttle-cabin/api/flow/v1/driver/leave") + Observable leaveStation(@Header ("appId") String appId, @Header("ticket") String ticket, @Body BusUpdateSiteStatusRequest request); + + /** + * 到站 更新到站信息 + * @param request + * @return + */ + @Headers({"Content-type:application/json;charset=UTF-8"}) + @POST("/och-shuttle-cabin/api/flow/v1/driver/arrive") + Observable arriveSiteStation(@Header ("appId") String appId,@Header("ticket") String ticket,@Body BusUpdateSiteStatusRequest request); + + + /** + * 到站查询下车乘客 + * @param request + * @return + */ + @Headers({"Content-type:application/json;charset=UTF-8"}) + @POST("/och-shuttle-cabin/api/business/v1/driver/siteArrivedOrders") + Observable< QueryLeaveAwayPassengersResponse > queryStationLeaveAwayPassengers(@Header ("appId") String appId,@Header("ticket") String ticket,@Body QueryLeaveAwayPassengersRequest request); + + /** + * + * @param appId + * @param ticket + * @param sn + * @return todo 修改结构 + */ + @Headers({"Content-type:application/json;charset=UTF-8"}) + @GET("/och-shuttle-cabin/api/business/v1/driver/servicingOrders/query") + Observable queryBusOrders(@Header ("appId") String appId, @Header("ticket") String ticket, @Query("sn") String sn); + + /** + * 查询车辆配置的所有路线 + * @param appId + * @param ticket + * @param sn + * @return + */ + @GET("/och-shuttle-cabin/api/business/v1/driver/bindLine/query") + Observable queryBusLines(@Header ("appId") String appId, @Header("ticket") String ticket, @Query("sn") String sn); + + /** + * 查询路线当天的任务 + * @param appId + * @param ticket + * @param lineId 线路id + * @return + */ + @GET("/och-shuttle-cabin/api/business/v1/driver/task/query") + Observable queryBusTaskByLineId(@Header ("appId") String appId, @Header("ticket") String ticket, @Query("lineId") String lineId); + + /** + * 中止任务 + * @param appId + * @param ticket + * @param data + * @return + */ + @POST("/och-shuttle-cabin/api/flow/v1/driver/abortTask") + Observable abortTask(@Header ("appId") String appId, @Header("ticket") String ticket, @Body BusCloseTaskRequest data); + + /** + * 任务正常跑完结束 + * @param appId + * @param ticket + * @param data + * @return + */ + @Headers( {"Content-type:application/json;charset=UTF-8"} ) + @POST("/och-shuttle-cabin/api/flow/v1/driver/endTask") + Observable endTask(@Header ("appId") String appId, @Header("ticket") String ticket, @Body BusCloseTaskRequest data); +} + diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/net/OrderServiceManager.kt b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/net/OrderServiceManager.kt new file mode 100644 index 0000000000..1857146fcd --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/net/OrderServiceManager.kt @@ -0,0 +1,203 @@ +package com.mogo.och.bus.net + +import android.content.Context +import com.mogo.cloud.passport.MoGoAiCloudClientConfig +import com.mogo.eagle.core.data.BaseData +import com.mogo.eagle.core.network.MoGoRetrofitFactory +import com.mogo.och.bus.bean.* +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.network.OchCommonSubscribeImpl +import com.mogo.och.common.module.biz.network.interceptor.transformTry + +/** + * @author: wangmingjun + * @date: 2021/10/20 + */ +object OrderServiceManager { + + private val mService: IBascApiService = MoGoRetrofitFactory.getInstance(OchCommonConst.getShuttleUrl()).create( + IBascApiService::class.java + ) + + + /** + * 查询小巴车当前任务 + * @param context + * @param callback + */ + @JvmStatic + fun queryBusRoutes(context: Context, callback: OchCommonServiceCallback?) { + //获取当前高德坐标 + 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? + ) { + 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?) { + 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?) { + 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? + ) { + 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? + ) { + 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? + ) { + mService.queryStationLeaveAwayPassengers( + MoGoAiCloudClientConfig.getInstance().serviceAppId, + MoGoAiCloudClientConfig.getInstance().token, + QueryLeaveAwayPassengersRequest(seq, siteId) + ) + .transformTry() + .subscribe(OchCommonSubscribeImpl(context, callback, "queryStationLeaveAwayPassengers")) + } + + /** + * 查询小巴车订单 + * @param context + * @param callback + */ + @JvmStatic + fun queryBusOrders(context: Context, callback: OchCommonServiceCallback?) { + mService.queryBusOrders( + MoGoAiCloudClientConfig.getInstance().serviceAppId, + MoGoAiCloudClientConfig.getInstance().token, + MoGoAiCloudClientConfig.getInstance().sn + ) + .transformTry() + .subscribe(OchCommonSubscribeImpl(context, callback, "queryBusOrders")) + } + @JvmStatic + fun queryBusLines(context: Context, callback: OchCommonServiceCallback?) { + 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? + ) { + mService.queryBusTaskByLineId( + MoGoAiCloudClientConfig.getInstance().serviceAppId, + MoGoAiCloudClientConfig.getInstance().token, + lineId + ) + .transformTry() + .subscribe(OchCommonSubscribeImpl(context, callback, "queryBusLines")) + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/net/login/LoginBusImpl.kt b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/net/login/LoginBusImpl.kt new file mode 100644 index 0000000000..0f3c2d294f --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/net/login/LoginBusImpl.kt @@ -0,0 +1,47 @@ +package com.mogo.och.bus.net.login + +import android.content.Context +import com.mogo.eagle.core.data.BaseData +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.TaxiLogoutReqBean +import com.mogo.och.common.module.biz.network.LoginDefaultManage +import com.mogo.och.common.module.biz.network.OchCommonServiceCallback + +class LoginBusImpl: LoginDefaultManage { + + override fun getPhoneCode( + context: Context, phone: String?, + callback: OchCommonServiceCallback? + ) { + OchCommonServiceManager.getPhoneCode(context,phone,callback) + } + + override fun gotoLoginBycode( + context: Context, + phone: String?, + code: String?, + location4Login: TaxiLoginReqBean.Location4Login?, + callback: OchCommonServiceCallback? + ) { + OchCommonServiceManager.gotoLoginBycode(context,phone,code,location4Login,callback) + } + + override fun logout( + context: Context, + location4Login: TaxiLogoutReqBean.Location4Login?, + callback: OchCommonServiceCallback? + ) { + OchCommonServiceManager.logout(context,location4Login,callback) + } + + override fun queryDriverServiceStatus( + context: Context, + callback: OchCommonServiceCallback? + ) { + OchCommonServiceManager.queryDriverServiceStatus(context,callback) + } + + +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/net/login/OchCommonServiceManager.kt b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/net/login/OchCommonServiceManager.kt new file mode 100644 index 0000000000..d331b69633 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/net/login/OchCommonServiceManager.kt @@ -0,0 +1,107 @@ +package com.mogo.och.bus.net.login + +import android.content.Context +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.eagle.core.data.BaseData +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 by pangfan on 2021/8/19 + */ +object OchCommonServiceManager { + + private const val TAG = "OchCommonServiceManager" + + private val mLoginServiceApi: OchLoginServiceApi = + MoGoRetrofitFactory.getInstance(OchCommonConst.getShuttleUrl()).create( + OchLoginServiceApi::class.java + ) + + /** + * 获取手机验证码 + * @param context + * @param callback + */ + @JvmStatic + fun getPhoneCode( + context: Context, phone: String?, + callback: OchCommonServiceCallback? + ) { + mLoginServiceApi.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? + ) { + val sn = MoGoAiCloudClientConfig.getInstance().sn + mLoginServiceApi.gotoLoginBycode4Bus( + MoGoAiCloudClientConfig.getInstance().serviceAppId, + MoGoAiCloudClientConfig.getInstance().token, + TaxiLoginReqBean(phone, code, sn, location4Login) + ).transformTry().subscribe(OchCommonSubscribeImpl(context, callback, "gotoLoginBycode")) + } + + /** + * 登出 + */ + @JvmStatic + fun logout( + context: Context, + location4Login: TaxiLogoutReqBean.Location4Login?, + callback: OchCommonServiceCallback? + ) { + mLoginServiceApi.logout4Bus( + MoGoAiCloudClientConfig.getInstance().serviceAppId, + MoGoAiCloudClientConfig.getInstance().token, + TaxiLogoutReqBean(MoGoAiCloudClientConfig.getInstance().sn, location4Login) + ).transformTry().subscribe(OchCommonSubscribeImpl(context, callback, "logout")) + } + + /** + * 接单状态和登录状态查询 + * + * @param context + * @param callback + */ + @JvmStatic + fun queryDriverServiceStatus( + context: Context, + callback: OchCommonServiceCallback? + ) { + if (MoGoAiCloudClientConfig.getInstance().token.isEmpty()) { + callback?.onFail(OchCommonConst.WAIT_TAKEN, "等待令牌中请稍等") + MoGoAiCloudClient.getInstance().refreshToken() + return + } + mLoginServiceApi.queryDriverServiceStatusAndLoginStatus( + MoGoAiCloudClientConfig.getInstance().serviceAppId, + MoGoAiCloudClientConfig.getInstance().token, + MoGoAiCloudClientConfig.getInstance().sn + ).transformTry() + .subscribe(OchCommonSubscribeImpl(context, callback, "queryDriverServiceStatus")) + } + +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/net/login/OchLoginServiceApi.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/net/login/OchLoginServiceApi.java new file mode 100644 index 0000000000..81a0206a40 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/net/login/OchLoginServiceApi.java @@ -0,0 +1,65 @@ +package com.mogo.och.bus.net.login; + +import com.mogo.eagle.core.data.BaseData; +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 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.Path; +import retrofit2.http.Query; + +/** + * Created by pangfan on 2021/8/19 + *

+ * 网约车-出租车接口定义 + */ +interface OchLoginServiceApi { + /** + * 获取手机验证码 + * + * @return + */ + @Headers( {"Content-type:application/json;charset=UTF-8"} ) + @POST( "/och-shuttle-cabin/api/sms/v1/driver/sendSms" ) + Observable getPhoneCode(@Header("appId") String appId + , @Header("ticket") String ticket, @Body TaxiLoginSmsReqBean data); + + /** + * 通过验证码登录 + * @param appId + * @param ticket + * @param data + * @return + */ + @Headers( {"Content-type:application/json;charset=UTF-8"} ) + @POST( "/och-shuttle-cabin/api/flow/v1/driver/startOperation" ) + Observable gotoLoginBycode4Bus(@Header("appId") String appId + , @Header("ticket") String ticket, @Body TaxiLoginReqBean data); + + /** + * 登出接口 + */ + @Headers({"Content-type:application/json;charset=UTF-8"}) + @POST("/och-shuttle-cabin/api/flow/v1/driver/endOperation") + Observable logout4Bus(@Header("appId") String appId, @Header("ticket") String ticket, + @Body TaxiLogoutReqBean data); + + /** + * 接单状态和登录状态查询 出租车司机端、小巴车司机端、小巴车乘客端 + * @param sn + * @return + */ + @Headers( {"Content-type:application/json;charset=UTF-8"} ) + @GET( "/och-shuttle-cabin/api/business/v1/driver/loginStatus") + Observable queryDriverServiceStatusAndLoginStatus(@Header("appId") String appId + , @Header("ticket") String ticket, @Query("sn") String sn); + +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/presenter/BusLinePresenter.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/presenter/BusLinePresenter.java new file mode 100644 index 0000000000..9411be65fd --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/presenter/BusLinePresenter.java @@ -0,0 +1,110 @@ +package com.mogo.och.bus.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.bus.bean.BusQueryLineTaskResponse; +import com.mogo.och.bus.bean.BusQueryLinesResponse; +import com.mogo.och.bus.callback.IBusLinesCallback; +import com.mogo.och.bus.model.BusLineModel; +import com.mogo.och.bus.model.OrderModel; +import com.mogo.och.bus.ui.BusSwitchLineView; + +import java.util.concurrent.TimeUnit; + +import io.reactivex.Observable; +import io.reactivex.disposables.Disposable; + +/** + * @author: wangmingjun + * @date: 2022/2/9 + */ +public class BusLinePresenter extends Presenter implements IBusLinesCallback { + + private Disposable subscribe; + + public BusLinePresenter(BusSwitchLineView view) { + super(view); + BusLineModel.getInstance().init(); + OrderModel.getInstance().init(); + } + + @Override + public void onCreate(@NonNull LifecycleOwner owner) { + super.onCreate(owner); + initListener(); + } + + private void initListener() { + BusLineModel.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(BusQueryLinesResponse lines) { + runOnUIThread(() -> mView.onBusLinesChange(lines)); + } + + @Override + public void onChangeLineIdSuccess() { + OrderModel.getInstance().clearBusStationDatas(); + runOnUIThread(() -> mView.onChangeLineIdSuccess()); + } + + public void queryBusLines(){ + BusLineModel.getInstance().queryBusLines(); + } + + public void queryBusLineTasks(int lineId, int position,boolean close){ + if(subscribe!=null&&!subscribe.isDisposed()){ + subscribe.dispose(); + } + if(close){ + return; + } + BusLineModel.getInstance().queryBusLineTasksById(lineId,position,false); + subscribe = Observable.interval(3, TimeUnit.MINUTES).subscribe(aLong -> { + BusLineModel.getInstance().queryBusLineTasksById(lineId,position,true); + }); + } + + public void commitSwitchLineId(int taskId,int lineId){ + BusLineModel.getInstance().commitSwitchLineId(taskId,lineId); + } + + public void removeListener(){ + BusLineModel.getInstance().setBusLinesCallback(null); + } + + public void queryBusRoutes(){ + OrderModel.getInstance().queryBusRoutes(); + } + + @Override + public void onDestroy(@NonNull LifecycleOwner owner) { + super.onDestroy(owner); + if(subscribe!=null&&!subscribe.isDisposed()){ + subscribe.dispose(); + } + } + + + @Override + public void onBusLineTasks(BusQueryLineTaskResponse o, int position,boolean autoRefresh) { + mView.onBusLineTasks(o,position,autoRefresh); + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/presenter/BusModelLoopManager.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/presenter/BusModelLoopManager.java new file mode 100644 index 0000000000..3c8415d86c --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/presenter/BusModelLoopManager.java @@ -0,0 +1,77 @@ +package com.mogo.och.bus.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.bus.constant.BusConst; +import com.mogo.och.bus.model.OrderModel; + +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 BusModelLoopManager { + + private static final String TAG = BusModelLoopManager.class.getSimpleName(); + + private static final class SingletonHolder { + private static final BusModelLoopManager INSTANCE = new BusModelLoopManager(); + } + + public static BusModelLoopManager getInstance() { + return SingletonHolder.INSTANCE; + } + + private Disposable mHeartbeatDisposable; //心跳轮询 +// private Disposable mQueryPassengerDisposable; //查询核销乘客 + +// public void startQueryPassengerWriteOffLoop() { +// if (mQueryPassengerDisposable != null && !mQueryPassengerDisposable.isDisposed()) { +// return; +// } +// CallerLogger.INSTANCE.i(M_BUS + TAG, "startQueryPassengerWriteOffLoop()"); +// mQueryPassengerDisposable = Observable.interval(LOOP_DELAY_500, +// LOOP_PASSENGER_5S, TimeUnit.MILLISECONDS) +// .map((aLong -> aLong + 1)) +// .subscribeOn(Schedulers.io()) +// .observeOn(AndroidSchedulers.mainThread()) +// .subscribe(aLong -> BusOrderModel.getInstance().queryPassengerWriteOff()); +// } + +// public void stopQueryPassengerWriteOffLoop() { +// if (mQueryPassengerDisposable != null) { +// CallerLogger.INSTANCE.i(M_BUS + TAG, "stopQueryPassengerWriteOffLoop()"); +// mQueryPassengerDisposable.dispose(); +// mQueryPassengerDisposable = null; +// } +// } + + public void startHeartbeatLoop() { + if (mHeartbeatDisposable != null && !mHeartbeatDisposable.isDisposed()) { + return; + } + CallerLogger.INSTANCE.i(M_BUS + TAG, "startHeartbeatLoop()"); + mHeartbeatDisposable = Observable.interval(BusConst.LOOP_DELAY, + BusConst.LOOP_PERIOD_60S, TimeUnit.MILLISECONDS) + .map((aLong -> aLong + 1)) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(aLong -> OrderModel.getInstance().runCarHeartbeat()); + } + + public void stopHeartbeatLoop() { + if (mHeartbeatDisposable != null) { + CallerLogger.INSTANCE.i(M_BUS + TAG, "stopHeartbeatLoop()"); + mHeartbeatDisposable.dispose(); + mHeartbeatDisposable = null; + } + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/presenter/BusPresenter.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/presenter/BusPresenter.java new file mode 100644 index 0000000000..a0885dbae8 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/presenter/BusPresenter.java @@ -0,0 +1,343 @@ +package com.mogo.och.bus.presenter; + +import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS; + +import android.os.Looper; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +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.data.map.MogoLocation; +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.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.fragment.BusFragment; +import com.mogo.och.bus.model.OrderModel; +import com.mogo.och.bus.util.BusTrajectoryManager; +import com.mogo.och.common.module.biz.bean.DriverStatusQueryRespBean; +import com.mogo.och.common.module.biz.callback.ILoginCallback; +import com.mogo.och.common.module.biz.constant.LoginStatusManager; +import com.mogo.och.common.module.manager.OCHAdasAbilityManager; +import com.mogo.och.common.module.voice.VoiceNotice; + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +import mogo.telematics.pad.MessagePad; +import mogo_msg.MogoReportMsg; +import system_master.SystemStatusInfo; + +/** + * 网约车小巴 + * + * @author tongchenfei + */ +public class BusPresenter extends Presenter + implements IRefreshBusStationsCallback, ISlidePannelHideCallback + , IMoGoAutopilotStatusListener, IBusControllerStatusCallback, ILoginCallback, IPassengerCallback, IBusADASStatusCallback { + + private static final String TAG = "BusPresenter"; + + private int currentAutopilotStatus = -1; + private List mStationList = new ArrayList<>(); + private int mCurrentStation = 0; + + public BusPresenter(BusFragment view) { + super(view); + //2021.11.1 鹰眼架构整合,由IMoGoAutopilotStatusListener逐步替代IMogoAdasOCHCallback接口 + CallerAutoPilotStatusListenerManager.INSTANCE.addListener(TAG, this); + OrderModel.getInstance().init(); + OCHAdasAbilityManager.getInstance().init(AbsMogoApplication.getApp()); + } + + @Override + public void onCreate(@NonNull LifecycleOwner owner) { + super.onCreate(owner); + initModelListener(); + } + + @Override + public void onDestroy(@NonNull LifecycleOwner owner) { + super.onDestroy(owner); + OrderModel.getInstance().release(); + releaseListener(); + } + + public void initModelListener() { + OrderModel.getInstance().setRefreshBusStationsCallback(this); + OrderModel.getInstance().setSlidePanelHideCallback(this); + OrderModel.getInstance().setControllerStatusCallback(this); + OrderModel.getInstance().setPassengerCallback(this); + OrderModel.getInstance().setAdasStatusCallback(this); + } + + public void releaseListener() { + OrderModel.getInstance().setRefreshBusStationsCallback(null); + OrderModel.getInstance().setSlidePanelHideCallback(null); + OrderModel.getInstance().setControllerStatusCallback(null); + OrderModel.getInstance().setPassengerCallback(null); + OrderModel.getInstance().setAdasStatusCallback(null); + OCHAdasAbilityManager.getInstance().release(); + } + + public void abortTask() { + OrderModel.getInstance().abortTask(); + } + + public void autoDriveToNextStation() { + currentAutopilotStatus = -1; + OrderModel.getInstance().autoDriveToNextStation(); +// isRestartAutopilot = false; + } + + public void restartAutopilot() { + if (OrderModel.getInstance().isGoingToNextStation()){ + currentAutopilotStatus = -1; + OrderModel.getInstance().restartAutopilot(); +// isRestartAutopilot = true; + } + } + + // 登出 + public void logout() { + OrderModel.getInstance().logout(); + } + + @Override + public void updateBusTaskStatus(String lineName,String lineTime, + List stationList, + int arrivingOrArrivedIndex, + boolean isArrived) { + mStationList.clear(); + mStationList.addAll(stationList); + if (arrivingOrArrivedIndex == 0 || isArrived){ + mCurrentStation = arrivingOrArrivedIndex; + }else { + mCurrentStation = arrivingOrArrivedIndex -1; + } + CallerLogger.INSTANCE.d(M_BUS + "BusOrderModel =", " mCurrentStation =" + mCurrentStation); + if (mView != null) { + runOnUIThread(() -> mView.updateBusTaskStatus(lineName,lineTime, + stationList, arrivingOrArrivedIndex, isArrived)); + } + } + + @Override + public void updateEmptyUi() { + runOnUIThread(() -> mView.updateLineEmptyUI()); + } + + @Override + public void clearBusStationsMarkers() { + runOnUIThread(() -> mView.clearBusStationsMarkers()); + } + + @Override + public void hideSlidePanel() { + if (mView != null) { + mView.hideSlidePanel(); + mView.setArrivedClikable(true); + } + } + + @Override + public void onAutopilotArriveAtStation(MessagePad.ArrivalNotification arrivalNotification) { + CallerLogger.INSTANCE.e( M_BUS + TAG, "行程日志-onAutopilotArriveAtStation arrive"); + OrderModel.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) { + // 设置UI【自动驾驶】按钮是否展示 + runOnUIThread(() -> mView.onAutopilotEnableChange(true)); + } + if (FunctionBuildConfig.isDemoMode + && ( + (mCurrentStation >= 0 && mCurrentStation <= mStationList.size() - 1) + && OrderModel.getInstance().isGoingToNextStation() + ) + ) { + CallerLogger.INSTANCE.d(M_BUS + "BusOrderModel=", "有美化功能"); + return; + } + if (currentAutopilotStatus != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE) { + currentAutopilotStatus = IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE; + } + // 改变UI自动驾驶状态 + runOnUIThread(() -> mView.onAutopilotStatusChanged(currentAutopilotStatus)); + break; + case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING: + if (currentAutopilotStatus != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) { + currentAutopilotStatus = IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING; + OrderModel.getInstance().triggerStartServiceEvent( + OrderModel.getInstance().isRestartAutopilot(), true); + } + // 改变UI自动驾驶状态 + runOnUIThread(() -> mView.onAutopilotStatusChanged(currentAutopilotStatus)); + break; + case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE: + if (FunctionBuildConfig.isDemoMode + && ( + (mCurrentStation >= 0 && mCurrentStation <= mStationList.size() - 1) + && OrderModel.getInstance().isGoingToNextStation() + + ) + ) { + CallerLogger.INSTANCE.d(M_BUS + "BusOrderModel=", "有美化功能"); + return; + } + + if (currentAutopilotStatus != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE) { + currentAutopilotStatus = IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE; + } + runOnUIThread(() -> { + mView.onAutopilotStatusChanged(currentAutopilotStatus); + }); + break; + case IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING: + if (FunctionBuildConfig.isDemoMode + && ( + (mCurrentStation >= 0 && mCurrentStation <= mStationList.size() - 1) + && OrderModel.getInstance().isGoingToNextStation() + + ) + ) { + CallerLogger.INSTANCE.d(M_BUS + "BusOrderModel=", "有美化功能"); + return; + } + if (currentAutopilotStatus != IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING) { + currentAutopilotStatus = IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING; + } + 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(MogoLocation location) { + if (null != location) { + runOnUIThread(() -> mView.updateSpeedView((float) location.getGnssSpeed())); + } + } + + @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 onAutopilotRouteLineId(long lineId) { + + } + + @Override + public void onAutopilotGuardian(MogoReportMsg.MogoReportMessage guardianInfo) { + BusTrajectoryManager.getInstance().onAutopilotGuardian(guardianInfo); + } + + @Override + public void onAutopilotIpcConnectStatusChanged(int status, @Nullable String reason) { + } + + @Override + public void onAutopilotStatusRespByQuery(@NonNull SystemStatusInfo.StatusInfo status) { + + } + @Override + public void loginSuccess(DriverStatusQueryRespBean data) { + CallerLogger.INSTANCE.d(M_BUS + TAG, " loginStatus =" + LoginStatusManager.isLogin()); + if(LoginStatusManager.isLogin()){ + OrderModel.getInstance().startOrStopOrderLoop(true); + OrderModel.getInstance().queryBusRoutes(); + }else { + BusTrajectoryManager.getInstance().stopTrajReqLoop(); + OrderModel.getInstance().startOrStopOrderLoop(false); + BusTrajectoryManager.getInstance().stopTrajReqLoop(); + clearBusStationsMarkers(); + mView.hideSlidePanel(); + OrderModel.getInstance().closeBeautificationMode(); + } + } + + @Override + public void loginFail(boolean isLogin) { + + } + + @Override + public void playPassenger(WriteOffPassenger passenger) { + int passengerNum = passenger.passengerSize; + if (passengerNum > 1){ //多人播报 "x人" ---》x人核验通过 + VoiceNotice.showNotice(passengerNum+"人核验通过", AIAssist.LEVEL3); + OrderModel.getInstance().sendWriteOffNumToClient(passengerNum+"人核验通过"); + }else { //是 1 播放 "滴" 2022.11.09 改为: "核验通过" +// mView.playDI(); + VoiceNotice.showNotice("核验通过", AIAssist.LEVEL3); + OrderModel.getInstance().sendWriteOffNumToClient("核验通过"); + } + } + + @Override + public void onStartAdasFailure() { + runOnUIThread(() -> mView.stopAnimAndUpdateBtnStatus()); + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/receiver/TestBusBroadcastReceiver.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/receiver/TestBusBroadcastReceiver.java new file mode 100644 index 0000000000..b9ffc6d492 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/receiver/TestBusBroadcastReceiver.java @@ -0,0 +1,42 @@ +package com.mogo.och.bus.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.bus.constant.BusConst; + +/** + * 测试小巴车的场景 + * + * @author donghongyu + * @date 4/26/21 12:08 PM + */ +public class TestBusBroadcastReceiver 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(BusConst.BROADCAST_TEST_BUS_CONTROL_TYPE_EXTRA_KEY, 0); + CallerLogger.INSTANCE.d(M_BUS + TAG, "sceneType:" + sceneType); + + // 分发场景 + dispatchSceneTest(sceneType); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void dispatchSceneTest(int sceneType) { + + } + + +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/ui/BusStationCommonItem.kt b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/ui/BusStationCommonItem.kt new file mode 100644 index 0000000000..ed9f463413 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/ui/BusStationCommonItem.kt @@ -0,0 +1,99 @@ +package com.mogo.och.bus.ui + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.ImageView +import android.widget.LinearLayout +import androidx.core.content.ContextCompat +import com.mogo.och.bus.R +import com.mogo.och.common.module.utils.BlinkAnimationUtil +import kotlinx.android.synthetic.main.bus_stations_common_item.view.* + +/** + * @author: wangmingjun + * @date: 2022/9/15 + */ +class BusStationCommonItem @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : LinearLayout(context, attrs, defStyleAttr){ + + init { + LayoutInflater.from(context).inflate(R.layout.bus_stations_common_item,this,true) + } + + fun setStationName(name: String){ + busStationNameTv.text = name + } + + fun setStationNameColor(color: Int){ + busStationNameTv.setTextColor(color) + } + + fun setStationPointBg(type: Int) { // 0:灰色 过站 1:绿色 到站或者即将到站 2:蓝色:未到站 + BlinkAnimationUtil.clearAnimation(busCircleIv) + when (type) { + 0 -> { + busCircleIvBg.visibility = GONE + busCircleIv.setImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.icon_point_grey_bus + ) + ) + } + 1 -> { + busCircleIvBg.visibility = VISIBLE + busCircleIv.setImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.icon_point_green_bus + ) + ) + BlinkAnimationUtil.setAnimation(busCircleIv) + } + 2 -> { + busCircleIvBg.visibility = GONE + busCircleIv.setImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.icon_point_blue_bus + ) + ) + } + + } + } + + fun getCircleImageView() : ImageView{ + return busCircleIv + } + + fun setStationArrowBg(type: Int){// 0:灰色 过站 1:绿色 前往下一站 2:蓝色 未到站 + when(type){ + 0 -> busArrowBg.setImageResource(R.drawable.icon_arrow_grey_bus) + 1 -> busArrowBg.setImageResource(R.drawable.icon_arrow_green_bus) + 2 -> busArrowBg.setImageResource(R.drawable.icon_arrow_blue_bus) + } + + } + + fun setStationTag(tag: String){ // 0:起 1:终 + if (tag.isNullOrEmpty()){ + busTagTxt.visibility = GONE + }else{ + busTagTxt.text = tag + busTagTxt.visibility = VISIBLE + } + } + + fun showOrHideStationArrowBg(isShow:Boolean){ + if (isShow){ + busArrowBg.visibility = VISIBLE + }else{ + busArrowBg.visibility = GONE + } + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/ui/BusSwitchLineActivity.kt b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/ui/BusSwitchLineActivity.kt new file mode 100644 index 0000000000..57d37c2805 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/ui/BusSwitchLineActivity.kt @@ -0,0 +1,222 @@ +package com.mogo.och.bus.ui + +import android.graphics.Point +import android.os.Bundle +import android.view.Gravity +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.ImageView +import android.widget.TextView +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.SharedPrefs +import com.mogo.och.bus.presenter.BusLinePresenter +import com.mogo.och.bus.ui.adapter.SwitchLineAdapter +import com.mogo.och.bus.bean.BusQueryLinesResponse +import com.mogo.och.bus.ui.adapter.OpenItemAnimator +import com.mogo.eagle.core.utilcode.mogo.view.SpacesItemDecoration +import com.mogo.eagle.core.utilcode.util.ToastUtils +import com.mogo.och.bus.R +import com.mogo.och.bus.bean.BusQueryLineTaskResponse +import java.util.ArrayList + +/** + * @author: wangmingjun + * @date: 2022/2/8 + */ +class BusSwitchLineActivity : MvpActivity(), + View.OnClickListener, BusSwitchLineView { + + companion object{ + const val LASTCOMMITLINEID = "lastcommitlineid" + } + + private lateinit var mClose: ImageView + private lateinit var mNoDatasView: ConstraintLayout + private lateinit var mLinesListView: RecyclerView + private lateinit var mLineCommitBtn: TextView + private lateinit var mAdapter: SwitchLineAdapter + private lateinit var linearLayoutManager:LinearLayoutManager + private val mData: MutableList = ArrayList() + override fun getLayoutId(): Int { + return R.layout.activity_bus_switch_line + } + + override fun createPresenter(): BusLinePresenter { + return BusLinePresenter(this) + } + + override fun initViews() { + initWH() + initView() + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + initDatas() + } + + /** + * 初始化view + */ + private fun 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) + linearLayoutManager = LinearLayoutManager(this) + mLinesListView.setLayoutManager(linearLayoutManager) + mLinesListView.setItemAnimator(OpenItemAnimator()) + mAdapter = SwitchLineAdapter(applicationContext, mData) + mLinesListView.addItemDecoration( + SpacesItemDecoration( + 4 + ) + ) + mLinesListView.setAdapter(mAdapter) + //设置item 点击事件 + mAdapter.setOnLineItemClickListener(object :SwitchLineAdapter.LineItemClickListener{ + override fun onItemClick(position: Int, close: Boolean) { + mPresenter?.queryBusLineTasks(mData[position].lineId, position, close) + } + }) + } + + /** + * 设置布局宽高 + */ + private fun initWH() { + val window = window + val params = window.attributes + val windowManager = getSystemService(WINDOW_SERVICE) as WindowManager + val point = Point() + windowManager.defaultDisplay.getSize(point) //用于获取屏幕高度 + params.width = (point.x * 0.375).toInt() + params.height = ViewGroup.LayoutParams.MATCH_PARENT + window.attributes = params + window.setGravity(Gravity.START or Gravity.BOTTOM) + } + + /** + * 初始化数据 + */ + private fun initDatas() { + mPresenter?.queryBusLines() + } + + /** + * 查询返回绑定路线集合 + * @param data + */ + override fun onBusLinesChange(data: BusQueryLinesResponse?) { + if (null == data) { + showNoData(true) + return + } + var lastCommitLineid = SharedPrefs.getInstance(this).getInt(LASTCOMMITLINEID, -1) + if (data.data != null && data.data.size > 0) { + showNoData(false) + mData.clear() + mData.addAll(data.data) + mAdapter.notifyDataSetChanged() + if(lastCommitLineid>0){ + mData.forEachIndexed { index, line -> + if(line.lineId==lastCommitLineid){ + line.open = true + mPresenter?.queryBusLineTasks(line.lineId,index,false) + return + } + } + } + } else { + showNoData(true) + } + } + + override fun onChangeLineIdSuccess() { + ToastUtils.showLong(resources.getString(R.string.bus_change_line_commit_tip_s)) + mPresenter?.queryBusRoutes() + mAdapter.setOnLineItemClickListener(null) + mPresenter?.removeListener() + finish() + } + + override fun onBusLineTasks(lineTaskInfo: BusQueryLineTaskResponse?, position: Int,autoRefresh:Boolean) { + val result = mData[position] + if (result.taskList == null) { + result.taskList = ArrayList() + } + if (lineTaskInfo == null) { + result.haveTask = true + // 打开操作 + mAdapter.notifyItemChanged(position) + } else { + if (lineTaskInfo.data == null || lineTaskInfo.data.isEmpty()) { + result.haveTask = true + lineTaskInfo.data = ArrayList() + } + if (lineTaskInfo.data.size != result.taskList.size) { // 不相等有变动 重新赋值 + result.taskList.clear() + result.taskList.addAll(lineTaskInfo.data) + if(autoRefresh) { + mAdapter.checkTaskId = -1 + mAdapter.checkLineId = -1 + lineTaskInfo.data.forEach { + if (it.id == mAdapter.checkTaskId) { + mAdapter.checkTaskId = it.id + mAdapter.checkLineId = result.lineId + } + } + } + // 打开操作 + mAdapter.notifyItemChanged(position) + linearLayoutManager.stackFromEnd = (position==mData.size-1||position==mData.size-2)&&mData.size>6 + mLinesListView.smoothScrollToPosition(position) + }else if(lineTaskInfo.data.isEmpty()){ + mAdapter.notifyItemChanged(position) + } + } + } + + /** + * 有无数据UI显示 + * @param b + */ + private fun showNoData(b: Boolean) { + if (b) { + mLinesListView.visibility = View.GONE + mLineCommitBtn.visibility = View.GONE + mNoDatasView.visibility = View.VISIBLE + } else { + mLinesListView.visibility = View.VISIBLE + mLineCommitBtn.visibility = View.VISIBLE + mNoDatasView.visibility = View.GONE + } + } + + override fun onClick(v: View) { + //关闭dialog + if (v.id == R.id.switch_line_close) { + finish() + return + } + //切换路线提交 + if (v.id == R.id.switch_line_btn_commit) { + if(mAdapter.checkLineId!=-1&&mAdapter.checkTaskId!=-1){ + mPresenter?.commitSwitchLineId(mAdapter.checkTaskId,mAdapter.checkLineId) + }else{ + ToastUtils.showLong("请选择任务") + } + } + } + + override fun onDestroy() { + mPresenter!!.removeListener() + super.onDestroy() + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/ui/BusSwitchLineView.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/ui/BusSwitchLineView.java new file mode 100644 index 0000000000..6646068909 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/ui/BusSwitchLineView.java @@ -0,0 +1,18 @@ +package com.mogo.och.bus.ui; + +import com.mogo.commons.mvp.IView; +import com.mogo.och.bus.bean.BusQueryLineTaskResponse; +import com.mogo.och.bus.bean.BusQueryLinesResponse; + +/** + * @author: wangmingjun + * @date: 2022/2/10 + */ +public interface BusSwitchLineView extends IView { + + void onBusLinesChange(BusQueryLinesResponse data); + void onChangeLineIdSuccess(); + + void onBusLineTasks(BusQueryLineTaskResponse o, int position,boolean autoRefresh); +} + diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/ui/adapter/OpenItemAnimator.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/ui/adapter/OpenItemAnimator.java new file mode 100644 index 0000000000..1571739e3b --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/ui/adapter/OpenItemAnimator.java @@ -0,0 +1,655 @@ +package com.mogo.och.bus.ui.adapter; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.TimeInterpolator; +import android.animation.ValueAnimator; +import android.view.View; +import android.view.ViewPropertyAnimator; + +import androidx.annotation.NonNull; +import androidx.core.view.ViewCompat; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.SimpleItemAnimator; + +import java.util.ArrayList; +import java.util.List; + +/** + * This implementation of {@link RecyclerView.ItemAnimator} provides basic + * animations on remove, add, and move events that happen to the items in + * a RecyclerView. RecyclerView uses a DefaultItemAnimator by default. + * + * @see RecyclerView#setItemAnimator(RecyclerView.ItemAnimator) + */ +public class OpenItemAnimator extends DefaultItemAnimator { + private static final boolean DEBUG = false; + + private static TimeInterpolator sDefaultInterpolator; + + private ArrayList mPendingRemovals = new ArrayList<>(); + private ArrayList mPendingAdditions = new ArrayList<>(); + private ArrayList mPendingMoves = new ArrayList<>(); + private ArrayList mPendingChanges = new ArrayList<>(); + + ArrayList> mAdditionsList = new ArrayList<>(); + ArrayList> mMovesList = new ArrayList<>(); + ArrayList> mChangesList = new ArrayList<>(); + + ArrayList mAddAnimations = new ArrayList<>(); + ArrayList mMoveAnimations = new ArrayList<>(); + ArrayList mRemoveAnimations = new ArrayList<>(); + ArrayList mChangeAnimations = new ArrayList<>(); + + private static class MoveInfo { + public RecyclerView.ViewHolder holder; + public int fromX, fromY, toX, toY; + + MoveInfo(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) { + this.holder = holder; + this.fromX = fromX; + this.fromY = fromY; + this.toX = toX; + this.toY = toY; + } + } + + private static class ChangeInfo { + public RecyclerView.ViewHolder oldHolder, newHolder; + public int fromX, fromY, toX, toY; + private ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder) { + this.oldHolder = oldHolder; + this.newHolder = newHolder; + } + + ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, + int fromX, int fromY, int toX, int toY) { + this(oldHolder, newHolder); + this.fromX = fromX; + this.fromY = fromY; + this.toX = toX; + this.toY = toY; + } + + @Override + public String toString() { + return "ChangeInfo{" + + "oldHolder=" + oldHolder + + ", newHolder=" + newHolder + + ", fromX=" + fromX + + ", fromY=" + fromY + + ", toX=" + toX + + ", toY=" + toY + + '}'; + } + } + + @Override + public void runPendingAnimations() { + boolean removalsPending = !mPendingRemovals.isEmpty(); + boolean movesPending = !mPendingMoves.isEmpty(); + boolean changesPending = !mPendingChanges.isEmpty(); + boolean additionsPending = !mPendingAdditions.isEmpty(); + if (!removalsPending && !movesPending && !additionsPending && !changesPending) { + // nothing to animate + return; + } + // First, remove stuff + for (RecyclerView.ViewHolder holder : mPendingRemovals) { + animateRemoveImpl(holder); + } + mPendingRemovals.clear(); + // Next, move stuff + if (movesPending) { + final ArrayList moves = new ArrayList<>(); + moves.addAll(mPendingMoves); + mMovesList.add(moves); + mPendingMoves.clear(); + Runnable mover = new Runnable() { + @Override + public void run() { + for (MoveInfo moveInfo : moves) { + animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY, + moveInfo.toX, moveInfo.toY); + } + moves.clear(); + mMovesList.remove(moves); + } + }; + if (removalsPending) { + View view = moves.get(0).holder.itemView; + ViewCompat.postOnAnimationDelayed(view, mover, getRemoveDuration()); + } else { + mover.run(); + } + } + // Next, change stuff, to run in parallel with move animations + if (changesPending) { + final ArrayList changes = new ArrayList<>(); + changes.addAll(mPendingChanges); + mChangesList.add(changes); + mPendingChanges.clear(); + Runnable changer = new Runnable() { + @Override + public void run() { + for (ChangeInfo change : changes) { + animateChangeImpl(change); + } + changes.clear(); + mChangesList.remove(changes); + } + }; + if (removalsPending) { + RecyclerView.ViewHolder holder = changes.get(0).oldHolder; + ViewCompat.postOnAnimationDelayed(holder.itemView, changer, getRemoveDuration()); + } else { + changer.run(); + } + } + // Next, add stuff + if (additionsPending) { + final ArrayList additions = new ArrayList<>(); + additions.addAll(mPendingAdditions); + mAdditionsList.add(additions); + mPendingAdditions.clear(); + Runnable adder = new Runnable() { + @Override + public void run() { + for (RecyclerView.ViewHolder holder : additions) { + animateAddImpl(holder); + } + additions.clear(); + mAdditionsList.remove(additions); + } + }; + if (removalsPending || movesPending || changesPending) { + long removeDuration = removalsPending ? getRemoveDuration() : 0; + long moveDuration = movesPending ? getMoveDuration() : 0; + long changeDuration = changesPending ? getChangeDuration() : 0; + long totalDelay = removeDuration + Math.max(moveDuration, changeDuration); + View view = additions.get(0).itemView; + ViewCompat.postOnAnimationDelayed(view, adder, totalDelay); + } else { + adder.run(); + } + } + } + + @Override + public boolean animateRemove(final RecyclerView.ViewHolder holder) { + resetAnimation(holder); + mPendingRemovals.add(holder); + return true; + } + + private void animateRemoveImpl(final RecyclerView.ViewHolder holder) { + final View view = holder.itemView; + final ViewPropertyAnimator animation = view.animate(); + mRemoveAnimations.add(holder); + animation.setDuration(getRemoveDuration()).alpha(0).setListener( + new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + dispatchRemoveStarting(holder); + } + + @Override + public void onAnimationEnd(Animator animator) { + animation.setListener(null); + view.setAlpha(1); + dispatchRemoveFinished(holder); + mRemoveAnimations.remove(holder); + dispatchFinishedWhenDone(); + } + }).start(); + } + + @Override + public boolean animateAdd(final RecyclerView.ViewHolder holder) { + resetAnimation(holder); + holder.itemView.setAlpha(0); + mPendingAdditions.add(holder); + return true; + } + + void animateAddImpl(final RecyclerView.ViewHolder holder) { + final View view = holder.itemView; + final ViewPropertyAnimator animation = view.animate(); + mAddAnimations.add(holder); + animation.alpha(1).setDuration(getAddDuration()) + .setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + dispatchAddStarting(holder); + } + + @Override + public void onAnimationCancel(Animator animator) { + view.setAlpha(1); + } + + @Override + public void onAnimationEnd(Animator animator) { + animation.setListener(null); + dispatchAddFinished(holder); + mAddAnimations.remove(holder); + dispatchFinishedWhenDone(); + } + }).start(); + } + + @Override + public boolean animateMove(final RecyclerView.ViewHolder holder, int fromX, int fromY, + int toX, int toY) { + final View view = holder.itemView; + fromX += (int) holder.itemView.getTranslationX(); + fromY += (int) holder.itemView.getTranslationY(); + resetAnimation(holder); + int deltaX = toX - fromX; + int deltaY = toY - fromY; + if (deltaX == 0 && deltaY == 0) { + dispatchMoveFinished(holder); + return false; + } + if (deltaX != 0) { + view.setTranslationX(-deltaX); + } + if (deltaY != 0) { + view.setTranslationY(-deltaY); + } + mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY)); + return true; + } + + void animateMoveImpl(final RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) { + final View view = holder.itemView; + final int deltaX = toX - fromX; + final int deltaY = toY - fromY; + if (deltaX != 0) { + view.animate().translationX(0); + } + if (deltaY != 0) { + view.animate().translationY(0); + } + // TODO: make EndActions end listeners instead, since end actions aren't called when + // vpas are canceled (and can't end them. why?) + // need listener functionality in VPACompat for this. Ick. + final ViewPropertyAnimator animation = view.animate(); + mMoveAnimations.add(holder); + animation.setDuration(getMoveDuration()).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + dispatchMoveStarting(holder); + } + + @Override + public void onAnimationCancel(Animator animator) { + if (deltaX != 0) { + view.setTranslationX(0); + } + if (deltaY != 0) { + view.setTranslationY(0); + } + } + + @Override + public void onAnimationEnd(Animator animator) { + animation.setListener(null); + dispatchMoveFinished(holder); + mMoveAnimations.remove(holder); + dispatchFinishedWhenDone(); + } + }).start(); + } + + @Override + public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, + int fromX, int fromY, int toX, int toY) { + if (oldHolder == newHolder) { + // Don't know how to run change animations when the same view holder is re-used. + // run a move animation to handle position changes. + return animateMove(oldHolder, fromX, fromY, toX, toY); + } + final float prevTranslationX = oldHolder.itemView.getTranslationX(); + final float prevTranslationY = oldHolder.itemView.getTranslationY(); + final float prevAlpha = oldHolder.itemView.getAlpha(); + resetAnimation(oldHolder); + int deltaX = (int) (toX - fromX - prevTranslationX); + int deltaY = (int) (toY - fromY - prevTranslationY); + // recover prev translation state after ending animation + oldHolder.itemView.setTranslationX(prevTranslationX); + oldHolder.itemView.setTranslationY(prevTranslationY); + oldHolder.itemView.setAlpha(prevAlpha); + if (newHolder != null) { + // carry over translation values + resetAnimation(newHolder); + newHolder.itemView.setTranslationX(-deltaX); + newHolder.itemView.setTranslationY(-deltaY); + newHolder.itemView.setAlpha(0); + } + mPendingChanges.add(new ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY)); + return true; + } + + void animateChangeImpl(final ChangeInfo changeInfo) { + final RecyclerView.ViewHolder holder = changeInfo.oldHolder; + final View view = holder == null ? null : holder.itemView; + final RecyclerView.ViewHolder newHolder = changeInfo.newHolder; + final View newView = newHolder != null ? newHolder.itemView : null; + if (view != null) { + final ViewPropertyAnimator oldViewAnim = view.animate().setDuration( + getChangeDuration()); + mChangeAnimations.add(changeInfo.oldHolder); + oldViewAnim.translationX(changeInfo.toX - changeInfo.fromX); + oldViewAnim.translationY(changeInfo.toY - changeInfo.fromY); + oldViewAnim.alpha(0).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + dispatchChangeStarting(changeInfo.oldHolder, true); + } + + @Override + public void onAnimationEnd(Animator animator) { + oldViewAnim.setListener(null); + view.setAlpha(1); + view.setTranslationX(0); + view.setTranslationY(0); + dispatchChangeFinished(changeInfo.oldHolder, true); + mChangeAnimations.remove(changeInfo.oldHolder); + dispatchFinishedWhenDone(); + } + }).start(); + } + if (newView != null) { + final ViewPropertyAnimator newViewAnimation = newView.animate(); + mChangeAnimations.add(changeInfo.newHolder); + newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()) + .alpha(1).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + dispatchChangeStarting(changeInfo.newHolder, false); + } + @Override + public void onAnimationEnd(Animator animator) { + newViewAnimation.setListener(null); + newView.setAlpha(1); + newView.setTranslationX(0); + newView.setTranslationY(0); + dispatchChangeFinished(changeInfo.newHolder, false); + mChangeAnimations.remove(changeInfo.newHolder); + dispatchFinishedWhenDone(); + } + }).start(); + } + } + + private void endChangeAnimation(List infoList, RecyclerView.ViewHolder item) { + for (int i = infoList.size() - 1; i >= 0; i--) { + ChangeInfo changeInfo = infoList.get(i); + if (endChangeAnimationIfNecessary(changeInfo, item)) { + if (changeInfo.oldHolder == null && changeInfo.newHolder == null) { + infoList.remove(changeInfo); + } + } + } + } + + private void endChangeAnimationIfNecessary(ChangeInfo changeInfo) { + if (changeInfo.oldHolder != null) { + endChangeAnimationIfNecessary(changeInfo, changeInfo.oldHolder); + } + if (changeInfo.newHolder != null) { + endChangeAnimationIfNecessary(changeInfo, changeInfo.newHolder); + } + } + private boolean endChangeAnimationIfNecessary(ChangeInfo changeInfo, RecyclerView.ViewHolder item) { + boolean oldItem = false; + if (changeInfo.newHolder == item) { + changeInfo.newHolder = null; + } else if (changeInfo.oldHolder == item) { + changeInfo.oldHolder = null; + oldItem = true; + } else { + return false; + } + item.itemView.setAlpha(1); + item.itemView.setTranslationX(0); + item.itemView.setTranslationY(0); + dispatchChangeFinished(item, oldItem); + return true; + } + + @Override + public void endAnimation(RecyclerView.ViewHolder item) { + final View view = item.itemView; + // this will trigger end callback which should set properties to their target values. + view.animate().cancel(); + // TODO if some other animations are chained to end, how do we cancel them as well? + for (int i = mPendingMoves.size() - 1; i >= 0; i--) { + MoveInfo moveInfo = mPendingMoves.get(i); + if (moveInfo.holder == item) { + view.setTranslationY(0); + view.setTranslationX(0); + dispatchMoveFinished(item); + mPendingMoves.remove(i); + } + } + endChangeAnimation(mPendingChanges, item); + if (mPendingRemovals.remove(item)) { + view.setAlpha(1); + dispatchRemoveFinished(item); + } + if (mPendingAdditions.remove(item)) { + view.setAlpha(1); + dispatchAddFinished(item); + } + + for (int i = mChangesList.size() - 1; i >= 0; i--) { + ArrayList changes = mChangesList.get(i); + endChangeAnimation(changes, item); + if (changes.isEmpty()) { + mChangesList.remove(i); + } + } + for (int i = mMovesList.size() - 1; i >= 0; i--) { + ArrayList moves = mMovesList.get(i); + for (int j = moves.size() - 1; j >= 0; j--) { + MoveInfo moveInfo = moves.get(j); + if (moveInfo.holder == item) { + view.setTranslationY(0); + view.setTranslationX(0); + dispatchMoveFinished(item); + moves.remove(j); + if (moves.isEmpty()) { + mMovesList.remove(i); + } + break; + } + } + } + for (int i = mAdditionsList.size() - 1; i >= 0; i--) { + ArrayList additions = mAdditionsList.get(i); + if (additions.remove(item)) { + view.setAlpha(1); + dispatchAddFinished(item); + if (additions.isEmpty()) { + mAdditionsList.remove(i); + } + } + } + + // animations should be ended by the cancel above. + //noinspection PointlessBooleanExpression,ConstantConditions + if (mRemoveAnimations.remove(item) && DEBUG) { + throw new IllegalStateException("after animation is cancelled, item should not be in " + + "mRemoveAnimations list"); + } + + //noinspection PointlessBooleanExpression,ConstantConditions + if (mAddAnimations.remove(item) && DEBUG) { + throw new IllegalStateException("after animation is cancelled, item should not be in " + + "mAddAnimations list"); + } + + //noinspection PointlessBooleanExpression,ConstantConditions + if (mChangeAnimations.remove(item) && DEBUG) { + throw new IllegalStateException("after animation is cancelled, item should not be in " + + "mChangeAnimations list"); + } + + //noinspection PointlessBooleanExpression,ConstantConditions + if (mMoveAnimations.remove(item) && DEBUG) { + throw new IllegalStateException("after animation is cancelled, item should not be in " + + "mMoveAnimations list"); + } + dispatchFinishedWhenDone(); + } + + private void resetAnimation(RecyclerView.ViewHolder holder) { + if (sDefaultInterpolator == null) { + sDefaultInterpolator = new ValueAnimator().getInterpolator(); + } + holder.itemView.animate().setInterpolator(sDefaultInterpolator); + endAnimation(holder); + } + + @Override + public boolean isRunning() { + return (!mPendingAdditions.isEmpty() + || !mPendingChanges.isEmpty() + || !mPendingMoves.isEmpty() + || !mPendingRemovals.isEmpty() + || !mMoveAnimations.isEmpty() + || !mRemoveAnimations.isEmpty() + || !mAddAnimations.isEmpty() + || !mChangeAnimations.isEmpty() + || !mMovesList.isEmpty() + || !mAdditionsList.isEmpty() + || !mChangesList.isEmpty()); + } + + /** + * Check the state of currently pending and running animations. If there are none + * pending/running, call {@link #dispatchAnimationsFinished()} to notify any + * listeners. + */ + void dispatchFinishedWhenDone() { + if (!isRunning()) { + dispatchAnimationsFinished(); + } + } + + @Override + public void endAnimations() { + int count = mPendingMoves.size(); + for (int i = count - 1; i >= 0; i--) { + MoveInfo item = mPendingMoves.get(i); + View view = item.holder.itemView; + view.setTranslationY(0); + view.setTranslationX(0); + dispatchMoveFinished(item.holder); + mPendingMoves.remove(i); + } + count = mPendingRemovals.size(); + for (int i = count - 1; i >= 0; i--) { + RecyclerView.ViewHolder item = mPendingRemovals.get(i); + dispatchRemoveFinished(item); + mPendingRemovals.remove(i); + } + count = mPendingAdditions.size(); + for (int i = count - 1; i >= 0; i--) { + RecyclerView.ViewHolder item = mPendingAdditions.get(i); + item.itemView.setAlpha(1); + dispatchAddFinished(item); + mPendingAdditions.remove(i); + } + count = mPendingChanges.size(); + for (int i = count - 1; i >= 0; i--) { + endChangeAnimationIfNecessary(mPendingChanges.get(i)); + } + mPendingChanges.clear(); + if (!isRunning()) { + return; + } + + int listCount = mMovesList.size(); + for (int i = listCount - 1; i >= 0; i--) { + ArrayList moves = mMovesList.get(i); + count = moves.size(); + for (int j = count - 1; j >= 0; j--) { + MoveInfo moveInfo = moves.get(j); + RecyclerView.ViewHolder item = moveInfo.holder; + View view = item.itemView; + view.setTranslationY(0); + view.setTranslationX(0); + dispatchMoveFinished(moveInfo.holder); + moves.remove(j); + if (moves.isEmpty()) { + mMovesList.remove(moves); + } + } + } + listCount = mAdditionsList.size(); + for (int i = listCount - 1; i >= 0; i--) { + ArrayList additions = mAdditionsList.get(i); + count = additions.size(); + for (int j = count - 1; j >= 0; j--) { + RecyclerView.ViewHolder item = additions.get(j); + View view = item.itemView; + view.setAlpha(1); + dispatchAddFinished(item); + additions.remove(j); + if (additions.isEmpty()) { + mAdditionsList.remove(additions); + } + } + } + listCount = mChangesList.size(); + for (int i = listCount - 1; i >= 0; i--) { + ArrayList changes = mChangesList.get(i); + count = changes.size(); + for (int j = count - 1; j >= 0; j--) { + endChangeAnimationIfNecessary(changes.get(j)); + if (changes.isEmpty()) { + mChangesList.remove(changes); + } + } + } + + cancelAll(mRemoveAnimations); + cancelAll(mMoveAnimations); + cancelAll(mAddAnimations); + cancelAll(mChangeAnimations); + + dispatchAnimationsFinished(); + } + + void cancelAll(List viewHolders) { + for (int i = viewHolders.size() - 1; i >= 0; i--) { + viewHolders.get(i).itemView.animate().cancel(); + } + } + + /** + * {@inheritDoc} + *

+ * If the payload list is not empty, DefaultItemAnimator returns true. + * When this is the case: + *

    + *
  • If you override {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)}, both + * ViewHolder arguments will be the same instance. + *
  • + *
  • + * If you are not overriding {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)}, + * then DefaultItemAnimator will call {@link #animateMove(RecyclerView.ViewHolder, int, int, int, int)} and + * run a move animation instead. + *
  • + *
+ */ + @Override + public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, + @NonNull List payloads) { + return !payloads.isEmpty() || super.canReuseUpdatedViewHolder(viewHolder, payloads); + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/ui/adapter/SwitchLineAdapter.kt b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/ui/adapter/SwitchLineAdapter.kt new file mode 100644 index 0000000000..741fd6480e --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/ui/adapter/SwitchLineAdapter.kt @@ -0,0 +1,175 @@ +package com.mogo.och.bus.ui.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import androidx.appcompat.widget.AppCompatTextView +import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.mogo.och.bus.R +import com.mogo.och.bus.bean.BusQueryLinesResponse +import com.mogo.och.bus.ui.adapter.SwitchLineAdapter.SwitchLineViewHolder +import kotlin.text.StringBuilder + +/** + * 路线列表adapter + */ +class SwitchLineAdapter( + private val mContext: Context, + private val mData: List +) : RecyclerView.Adapter() { + companion object{ + const val TAG = "SwitchLineAdapter" + } + // RecyclerView设置点击事件 + private var mItemClickListener: LineItemClickListener? = null + var checkLineId:Int = -1 + var checkTaskId:Int = -1 + override fun onCreateViewHolder( + parent: ViewGroup, + viewType: Int + ): SwitchLineViewHolder { + val view = LayoutInflater.from(mContext).inflate( + R.layout.bus_switch_line_list_item, parent, false + ) + return SwitchLineViewHolder(view) + } + + override fun onBindViewHolder(holder: SwitchLineViewHolder, position: Int) { + val currentPosition = holder.bindingAdapterPosition + val line = mData[currentPosition] + if(line.name!=null&&line.name.length>10){ + line.name = line.name.substring(0,10)+"…" + } + holder.lineName.text = line.name + val sb = StringBuilder() + if (line.endSiteName!=null&&line.endSiteName.length>10) { + sb.append(line.endSiteName.substring(0,5)) + sb.append("…") + sb.append(line.endSiteName.substring(line.endSiteName.length-5,line.endSiteName.length)) + }else{ + sb.append(line.endSiteName) + } + val string = mContext.getString(R.string.bus_line_goto_end, sb.toString()) + holder.lineEndName.text = string + holder.rvLineTask.layoutManager = GridLayoutManager(mContext, 3) + val switchLineTaskAdapter = SwitchLineTaskAdapter( + mContext, + checkTaskId, + line.taskList, + object : SwitchLineTaskAdapter.TaskItemClickListener { + override fun onItemClick(position: Int,isCheck:Boolean) { + if(isCheck) { + checkLineId = line.lineId + checkTaskId = line.taskList[position].id + }else{ + checkLineId=-1 + checkTaskId=-1 + } + } + }) + holder.rvLineTask.adapter = switchLineTaskAdapter + holder.rvLineTask.isFocusableInTouchMode = false + holder.actvShowMore.visibility = View.VISIBLE + + if(line.open){ + if(line.taskList==null||line.taskList.isEmpty()){ + holder.actvShowMore.text = mContext.getString(R.string.bus_switch_line_no_task) + holder.actvShowMore.setTextColor(ContextCompat.getColor(mContext,R.color.bus_color_4dffffff)) + holder.vLineTask.visibility = View.GONE + holder.rvLineTask.visibility = View.GONE + holder.selectIv.visibility = View.INVISIBLE + holder.itemView.setBackgroundResource(R.drawable.bus_shape_select_line_item_bg_normal) + }else { + holder.actvShowMore.text = mContext.getString(R.string.bus_switch_line_select_task) + holder.actvShowMore.setTextColor(ContextCompat.getColor(mContext,android.R.color.white)) + holder.vLineTask.visibility = View.VISIBLE + holder.rvLineTask.visibility = View.VISIBLE + holder.selectIv.visibility = View.VISIBLE + holder.itemView.setBackgroundResource(R.drawable.bus_shape_select_line_item_bg_selected) + holder.selectIv.apply { + pivotX = 9.5f + pivotY = 17f + rotation = 90f + } + } + }else{ + if(line.haveTask){ + holder.actvShowMore.text = mContext.getString(R.string.bus_switch_line_no_task) + holder.actvShowMore.setTextColor(ContextCompat.getColor(mContext,R.color.bus_color_4dffffff)) + holder.vLineTask.visibility = View.GONE + holder.rvLineTask.visibility = View.GONE + holder.selectIv.visibility = View.INVISIBLE + holder.itemView.setBackgroundResource(R.drawable.bus_shape_select_line_item_bg_normal) + }else { + holder.actvShowMore.text = mContext.getString(R.string.bus_switch_line_select_task) + holder.actvShowMore.setTextColor(ContextCompat.getColor(mContext,android.R.color.white)) + holder.vLineTask.visibility = View.GONE + holder.rvLineTask.visibility = View.GONE + holder.selectIv.visibility = View.VISIBLE + holder.itemView.setBackgroundResource(R.drawable.bus_shape_select_line_item_bg_normal) + holder.selectIv.apply { + pivotX = 9.5f + pivotY = 17f + rotation = 0f + } + } + } + + + //设置item点击事件 + holder.itemView.setOnClickListener { + if(holder.actvShowMore.text==mContext.getString(R.string.bus_switch_line_no_task)){ + return@setOnClickListener + } + mData.forEachIndexed { index, result -> + if(result.open){ + result.open = false; + notifyItemChanged(index) + if(result.taskList!=null) { + result.taskList.clear() + } + if(index==currentPosition){// 点击当前已经打开的item 去关闭定时网络请求 + mItemClickListener?.onItemClick(currentPosition,true) + return@setOnClickListener + } + } + } + mItemClickListener?.onItemClick(currentPosition,false) + line.open = holder.rvLineTask.visibility == View.GONE + } + } + + override fun getItemCount(): Int { + return mData.size + } + + fun setOnLineItemClickListener(itemClickListener: LineItemClickListener?) { + mItemClickListener = itemClickListener + } + + class SwitchLineViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val selectIv: ImageView + val lineName: AppCompatTextView//线路名称 + val lineEndName: AppCompatTextView //终点 + val actvShowMore: AppCompatTextView //选择时间 + val rvLineTask: RecyclerView// 排班时间 + val vLineTask: View// 白色分割线 + + init { + selectIv = itemView.findViewById(R.id.switch_line_item_select_iv) + lineName = itemView.findViewById(R.id.switch_line_name) + lineEndName = itemView.findViewById(R.id.switch_line_end_station) + rvLineTask = itemView.findViewById(R.id.rv_line_task_list) + vLineTask = itemView.findViewById(R.id.v_line_task) + actvShowMore = itemView.findViewById(R.id.actv_show_more) + } + } + + interface LineItemClickListener { + fun onItemClick(position: Int,close:Boolean) + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/ui/adapter/SwitchLineTaskAdapter.kt b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/ui/adapter/SwitchLineTaskAdapter.kt new file mode 100644 index 0000000000..8183e0efd4 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/ui/adapter/SwitchLineTaskAdapter.kt @@ -0,0 +1,76 @@ +package com.mogo.och.bus.ui.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.RecyclerView +import com.mogo.eagle.core.utilcode.util.TimeUtils +import com.mogo.och.bus.R +import com.mogo.och.bus.bean.BusQueryLineTaskResponse +import com.mogo.och.bus.ui.adapter.SwitchLineTaskAdapter.SwitchLineTaskViewHolder + +/** + * 路线列表adapter + */ +class SwitchLineTaskAdapter( + private val mContext: Context, + private var checkTaskId:Int, + private val mData: List?, + private val mTaskItemClickListener: TaskItemClickListener? +) : RecyclerView.Adapter() { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SwitchLineTaskViewHolder { + val view = LayoutInflater.from(mContext).inflate( + R.layout.bus_switch_line_list_task_item, parent, false + ) + return SwitchLineTaskViewHolder(view) + } + + override fun onBindViewHolder(holder: SwitchLineTaskViewHolder, position: Int) { + val currentPosition = holder.bindingAdapterPosition + val task = mData!![currentPosition] + val taskStartTime = TimeUtils.millis2String(task.taskStartTime, "HH:mm") + holder.lineTask.text = taskStartTime + if(checkTaskId==task.id){ + holder.lineTask.setBackgroundResource(R.drawable.bus_shape_select_line_item_time_bg_selected) + }else{ + holder.lineTask.setBackgroundResource(R.drawable.bus_shape_select_line_item_time_bg) + } + holder.lineTask.setOnClickListener { + if(checkTaskId==task.id){ + checkTaskId = -1 + mTaskItemClickListener?.onItemClick(currentPosition,false) + }else { + resetOther() + checkTaskId = task.id + mTaskItemClickListener?.onItemClick(currentPosition,true) + } + notifyItemChanged(currentPosition) + } + } + + private fun resetOther() { + mData?.forEachIndexed { index, result -> + if(result.id==checkTaskId){ + checkTaskId = -1 + notifyItemChanged(index) + } + } + } + + override fun getItemCount(): Int { + return mData?.size ?: 0 + } + + class SwitchLineTaskViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val lineTask: TextView // 时间 + init { + lineTask = itemView.findViewById(R.id.actv_line_task) + } + } + + interface TaskItemClickListener { + fun onItemClick(position: Int,isCheck:Boolean) + } +} \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/util/BDRouteDataTestUtils.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/util/BDRouteDataTestUtils.java new file mode 100644 index 0000000000..a9ff4aad99 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/util/BDRouteDataTestUtils.java @@ -0,0 +1,45 @@ +package com.mogo.och.bus.util; + +import com.mogo.och.bus.model.OrderModel; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.List; + +import mogo.telematics.pad.MessagePad; + +/** + * @author: wangmingjun + * @date: 2022/4/13 + */ +public class BDRouteDataTestUtils { + + static String jsonStr ="{\n" + + " \"models\": [\n" + + " {\n" + + " \"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19927760268911,\"lon\":116.73512607061035,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19927736555187,\"lon\":116.73498243020299,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19927135941599,\"lon\":116.73482951462647,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199260672670036,\"lon\":116.73468429259535,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199251260349946,\"lon\":116.73453933465,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19924691997577,\"lon\":116.7343756435551,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199247953493625,\"lon\":116.73421240809087,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19924986849947,\"lon\":116.73400425509712,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199249431152175,\"lon\":116.73378579041055,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199248921305724,\"lon\":116.73357811807278,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19925012387371,\"lon\":116.73337650020184,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199252270195075,\"lon\":116.73318223781153,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.1992521615169,\"lon\":116.73298632625203,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19925202633083,\"lon\":116.73279582043983,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199261230205735,\"lon\":116.73263403473568,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199327991681926,\"lon\":116.73251962434813,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19944850496711,\"lon\":116.73249661840195,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199582026896415,\"lon\":116.73251038561487,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199743326352014,\"lon\":116.73253087453938,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199908347167394,\"lon\":116.73255070500186,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200065950595445,\"lon\":116.7325720694418,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20022747460407,\"lon\":116.73259461416663,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200384057310536,\"lon\":116.73261575018056,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20053849777916,\"lon\":116.73263451936387,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200696919444624,\"lon\":116.7326540541723,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2008524952796,\"lon\":116.7326743511824,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20101429705625,\"lon\":116.73269393580199,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20118279997041,\"lon\":116.73271564378308,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201342388452076,\"lon\":116.73273653366076,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201476063822355,\"lon\":116.73275292393079,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20163479199852,\"lon\":116.73277440686762,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20181243476041,\"lon\":116.7328052766508,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201991767093304,\"lon\":116.7328453845644,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20215573733484,\"lon\":116.73287624009339,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202313648759784,\"lon\":116.73289887933315,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202434745374454,\"lon\":116.7329182210956,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20253164952098,\"lon\":116.73297539811277,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20258043275509,\"lon\":116.73312335324984,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20258233576585,\"lon\":116.73331077089557,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20257107560234,\"lon\":116.73351244039137,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202561578580514,\"lon\":116.73370176209845,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20256256788661,\"lon\":116.73391325024126,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20255633158834,\"lon\":116.73413195000244,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202543311179575,\"lon\":116.73436614303907,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20253067346457,\"lon\":116.73458032609663,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20251776111356,\"lon\":116.73477082198242,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202503997557805,\"lon\":116.73498624001282,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20249129260376,\"lon\":116.73518976336872,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247877796589,\"lon\":116.73537786253135,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20246651610268,\"lon\":116.73559239130266,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20245754388014,\"lon\":116.73574239922202,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20244749208,\"lon\":116.73589674090469,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243806550113,\"lon\":116.73607057284322,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243550556816,\"lon\":116.73628106525871,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243654127756,\"lon\":116.7364949950665,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243738221016,\"lon\":116.7367061649993,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243672476754,\"lon\":116.73691115930336,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243590788176,\"lon\":116.73710722104272,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202436434375336,\"lon\":116.73730688607075,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243749821501,\"lon\":116.73750140347998,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243625962803,\"lon\":116.73771330926793,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202434515480725,\"lon\":116.73791895606205,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2024326561388,\"lon\":116.73815206945737,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20243092086137,\"lon\":116.73838655528765,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202430876006126,\"lon\":116.73861890759498,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20242914053177,\"lon\":116.73882029918758,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20242843336561,\"lon\":116.73904465495175,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20242661219026,\"lon\":116.73922453252953,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202426462811076,\"lon\":116.7393708046956,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20242687134937,\"lon\":116.73954685547025,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20242694967377,\"lon\":116.73975021183773,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202424630601236,\"lon\":116.73999740812975,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202422502184625,\"lon\":116.74028266774337,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202419634158936,\"lon\":116.7405942561498,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241975959762,\"lon\":116.7409069557092,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241920524113,\"lon\":116.74120156191647,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241765540262,\"lon\":116.74149288504978,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241569149764,\"lon\":116.7418080096762,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202414529497084,\"lon\":116.74210262897205,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241419532155,\"lon\":116.74241767661879,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202413879360954,\"lon\":116.7427571218185,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241287045245,\"lon\":116.7431284691325,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241214965105,\"lon\":116.74343354359334,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241141271715,\"lon\":116.7437220210538,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2024080520075,\"lon\":116.74399113498052,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202391714280026,\"lon\":116.74427625698272,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20238163805639,\"lon\":116.74452083315958,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202379293010274,\"lon\":116.74475703837204,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202379007817086,\"lon\":116.7449961645494,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20237814181231,\"lon\":116.7452036063558,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202375477619896,\"lon\":116.74539567654291,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2023632396621,\"lon\":116.74555457589031,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20229396554444,\"lon\":116.7456716047369,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20217800547467,\"lon\":116.74574081942625,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202047498095304,\"lon\":116.74573659255675,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20188573786706,\"lon\":116.74571018281719,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201738240263026,\"lon\":116.74568463148606,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20157507049073,\"lon\":116.74565525041498,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20137985142042,\"lon\":116.745619970576,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201187335613575,\"lon\":116.74558631350607,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20098251429043,\"lon\":116.74555055587679,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2007748533628,\"lon\":116.74551426934663,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20057082986032,\"lon\":116.74547749663195,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20036944224329,\"lon\":116.74544156175533,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20016365229035,\"lon\":116.74540577510051,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.1999958572445,\"lon\":116.74537505807076,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19984100521566,\"lon\":116.7453433678602,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.1996863960282,\"lon\":116.74529675648621,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19953919567943,\"lon\":116.74525916493474,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19940587189373,\"lon\":116.74523402869453,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19929047792381,\"lon\":116.74518617038383,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922141745155,\"lon\":116.74506912884067,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19920798885308,\"lon\":116.744896716334,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19920912644279,\"lon\":116.74467216715483,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199209186509314,\"lon\":116.74448257515108,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19920910709997,\"lon\":116.74430613406223,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.1992100786082,\"lon\":116.74410888316238,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19921081961254,\"lon\":116.74391968819582,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19921040855518,\"lon\":116.7437082083402,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19921085053439,\"lon\":116.74346931155634,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19921197237373,\"lon\":116.74325149697013,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19921248248983,\"lon\":116.74301103786591,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.1992139724646,\"lon\":116.74277237066539,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199215818352386,\"lon\":116.74253219408898,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199216175018876,\"lon\":116.74228853120842,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199215970354246,\"lon\":116.74204663206451,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199216627492966,\"lon\":116.74183871233049,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19921789170398,\"lon\":116.74165788334192,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922000138535,\"lon\":116.74144512197054,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199221559127494,\"lon\":116.741249370491,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922287231889,\"lon\":116.7410525810756,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922229019589,\"lon\":116.74085266662037,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.1992216995901,\"lon\":116.74061957723823,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922263073874,\"lon\":116.74041638149129,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922478093337,\"lon\":116.7402123910757,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199227066091595,\"lon\":116.74003419421553,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199228634241756,\"lon\":116.73985841944678,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19922951636012,\"lon\":116.7397079274105,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199252095329484,\"lon\":116.73956265582487,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199346162997905,\"lon\":116.73944690416265,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199470799628024,\"lon\":116.73941941053417,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19962513314346,\"lon\":116.7394280706812,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199780626058924,\"lon\":116.73944255215424,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199961525343376,\"lon\":116.73945856750177,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20016196947193,\"lon\":116.73947572081121,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200384479551936,\"lon\":116.7394949225795,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200595083817475,\"lon\":116.73951027963179,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200792203321086,\"lon\":116.73952526850614,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200985930701684,\"lon\":116.73954125209579,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20115978977055,\"lon\":116.73955610094161,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201321019536124,\"lon\":116.7395695239138,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20147117943043,\"lon\":116.7395823299481,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20163699848565,\"lon\":116.73959633422596,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20178484338371,\"lon\":116.7396085776486,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201962185646316,\"lon\":116.73962351991214,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2021018923927,\"lon\":116.7396354059821,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2022137620686,\"lon\":116.73964348380458,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20232600820075,\"lon\":116.73961190446633,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20241090270993,\"lon\":116.73951649703137,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20245777783807,\"lon\":116.73937664238166,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20246906634823,\"lon\":116.73920146119093,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202470916682884,\"lon\":116.73898763065634,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247034830421,\"lon\":116.73878158418357,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20246978204673,\"lon\":116.73857680142473,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247082638905,\"lon\":116.73834517890637,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202471943178196,\"lon\":116.7381047689514,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247131648035,\"lon\":116.73787761484981,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202470799473765,\"lon\":116.73766230702478,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247013054322,\"lon\":116.73743619407796,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20246999515433,\"lon\":116.73724916823292,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247199652478,\"lon\":116.73704888970806,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202473960263525,\"lon\":116.73684083235807,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202474504753205,\"lon\":116.73665462440796,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20247501354581,\"lon\":116.73650710371837,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20246541231906,\"lon\":116.73635807696789,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.202426768984274,\"lon\":116.73622283382787,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20236638788854,\"lon\":116.73610589402243,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20227106919894,\"lon\":116.73600895001849,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2021428343084,\"lon\":116.73596816020945,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20197815580698,\"lon\":116.73594623645097,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20181789535303,\"lon\":116.73593148707488,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201667906886954,\"lon\":116.73591743008926,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.201505897730755,\"lon\":116.7359002912543,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20135083580946,\"lon\":116.73588579696379,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20118617904595,\"lon\":116.73586970398149,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20102374028594,\"lon\":116.73585314703226,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20085554043743,\"lon\":116.73583763953049,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20069451888229,\"lon\":116.73582073901778,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.200530837344964,\"lon\":116.73580314359012,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.2003608457064,\"lon\":116.73578183888779,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20021770046798,\"lon\":116.73575292592922,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.20003454701824,\"lon\":116.7357174959358,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19986125116602,\"lon\":116.73569499961796,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19969408518737,\"lon\":116.73567725223492,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19955533048882,\"lon\":116.73566375985422,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19943174810538,\"lon\":116.73564927714162,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19933167546824,\"lon\":116.735595995086,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.199280357603875,\"lon\":116.73546293260645,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19927848361656,\"lon\":116.73531579486274,\"speed\":0.0},{\"altitude\":0.0,\"angle\":0.0,\"duration\":0,\"lat\":40.19928127892504,\"lon\":116.73505848474375,\"speed\": 0.0\n" + + " }\n" + + " ]\n" + + "}"; + public static void converToRouteData(){ + List list = new ArrayList<>(); + + try { + JSONObject jsonObject = new JSONObject(jsonStr); + JSONArray jsonElements = jsonObject.getJSONArray("models"); + for (int i = 0; i < jsonElements.length(); i++) { + JSONObject s = jsonElements.getJSONObject(i); + MessagePad.Location.Builder builder = MessagePad.Location.newBuilder(); + builder.setLatitude(s.getDouble("lat")); + builder.setLongitude(s.getDouble("lon")); + list.add(builder.build()); + } + OrderModel.getInstance().debugUpdateOrderRoute(list); + } catch (JSONException e) { + e.printStackTrace(); + } + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/util/BusAnalyticsManager.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/util/BusAnalyticsManager.java new file mode 100644 index 0000000000..b37e399e18 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/util/BusAnalyticsManager.java @@ -0,0 +1,146 @@ +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; +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.commons.utils.MogoAnalyticUtils; +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; + +/** + * OCH Bus埋点工具 + * + * Created on 2022/3/24 + */ +public class BusAnalyticsManager { + + private static final class SingletonHolder { + private static final BusAnalyticsManager INSTANCE = new BusAnalyticsManager(); + } + + public static BusAnalyticsManager getInstance() { + return BusAnalyticsManager.SingletonHolder.INSTANCE; + } + + private String mStartAutopilotKey; + private HashMap mStartAutopilotParams = new HashMap<>(); + + private Runnable startAutopilotRunnable = () -> { + // 15s内未开启,上报失败埋点 + triggerStartAutopilotFailureEvent("", "15s后app等待超时"); + }; + + public void triggerStartAutopilotFailureEventByAdas(String failCode, String failMsg){ + removeWaitingCallback(); + triggerStartAutopilotFailureEvent(failCode, failMsg); + } + + private void triggerStartAutopilotFailureEvent(String failCode, String failMsg){ + if (mStartAutopilotParams.isEmpty()) return; + + CallerLogger.INSTANCE.e( M_BUS + "triggerStartAutopilotFailureEvent", failMsg ); + + if (CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() != + IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING){ + mStartAutopilotParams.put(BusConst.EVENT_PARAM_START_FAILURE_CODE, failCode); + mStartAutopilotParams.put(BusConst.EVENT_PARAM_START_FAILURE_MSG, failMsg); + } + mStartAutopilotParams.put(BusConst.EVENT_PARAM_START_RESULT + , CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() == + IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING); + + MogoAnalyticUtils.INSTANCE.track(mStartAutopilotKey, mStartAutopilotParams); + + clearStartAutopilotParams();//清空参数数据,防止误传 + } + + private void removeWaitingCallback() { + if (startAutopilotRunnable != null) { + UiThreadHandler.removeCallbacks(startAutopilotRunnable); + } + } + + public void clearStartAutopilotFailureMSG(){ + mStartAutopilotParams.put(BusConst.EVENT_PARAM_START_FAILURE_CODE, ""); + mStartAutopilotParams.put(BusConst.EVENT_PARAM_START_FAILURE_MSG, ""); + } + + private void clearStartAutopilotParams(){ + mStartAutopilotParams.clear(); + } + + /** + * 触发'开启自动驾驶'埋点流程 + * 开启自动驾驶,15s内成功则发送成功埋点,否则发送失败埋点 + * @param restart false(点击'滑动出发'启动)/true(接管后点击'自动驾驶'按钮启动) + * @param send 是否直接发送埋点(15s内开启成功则直接发送成功埋点) + */ + public void triggerStartAutopilotEvent( + boolean restart, boolean send, String startName, String endName, int lineId) { + mStartAutopilotKey = restart ? + BusConst.EVENT_KEY_RESTART_AUTOPILOT : BusConst.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(BusConst.EVENT_PARAM_SN, sn); + mStartAutopilotParams.put(BusConst.EVENT_PARAM_PLATE_NUM, TextUtils.isEmpty(plateNum) ? "" : plateNum); + mStartAutopilotParams.put(BusConst.EVENT_PARAM_ENV_ONLINE, + DebugConfig.getNetMode() == DebugConfig.NET_MODE_RELEASE ? true : false); + mStartAutopilotParams.put(BusConst.EVENT_PARAM_TIME, dateTime); + mStartAutopilotParams.put(BusConst.EVENT_PARAM_START_NAME, startName); + mStartAutopilotParams.put(BusConst.EVENT_PARAM_END_NAME, endName); + mStartAutopilotParams.put(BusConst.EVENT_PARAM_LINE_ID, lineId); + + if (send) { + if (mStartAutopilotParams.isEmpty()) return; + // 开启成功,上报埋点 + clearStartAutopilotFailureMSG(); + removeWaitingCallback(); + mStartAutopilotParams.put(BusConst.EVENT_PARAM_START_RESULT, true); + MogoAnalyticUtils.INSTANCE.track(mStartAutopilotKey, mStartAutopilotParams); + + clearStartAutopilotParams();//清空参数数据,防止误传 + } 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 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); + MogoAnalyticUtils.INSTANCE.track(BusConst.EVENT_KEY_AP_UNABLE_START_REASON, params); + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/util/BusSendTripInfoManager.kt b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/util/BusSendTripInfoManager.kt new file mode 100644 index 0000000000..b4da61f56f --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/util/BusSendTripInfoManager.kt @@ -0,0 +1,36 @@ +package com.mogo.och.bus.util + +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotControlManager +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) + CallerAutoPilotControlManager.sendTripInfo(type,lineName,departureStopName, arrivalStopName, isLastStop) + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/util/BusTrajectoryManager.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/util/BusTrajectoryManager.java new file mode 100644 index 0000000000..6cf6eb90c4 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/util/BusTrajectoryManager.java @@ -0,0 +1,206 @@ +package com.mogo.och.bus.util; + +import androidx.annotation.Nullable; + +import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters; +import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotControlManager; +import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger; +import com.mogo.eagle.core.utilcode.util.GsonUtils; +import com.mogo.och.bus.bean.BusRoutesResult; +import com.mogo.och.bus.constant.BusConst; +import com.mogo.och.bus.model.OrderModel; +import com.mogo.och.common.module.biz.constant.LoginStatusManager; +import com.zhidao.socket.utils.LoginStatusUtil; + +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 BusTrajectoryManager { + private static final String TAG = BusTrajectoryManager.class.getSimpleName(); + + private static final class SingletonHolder { + private static final BusTrajectoryManager INSTANCE = new BusTrajectoryManager(); + } + + public static BusTrajectoryManager getInstance() { + return BusTrajectoryManager.SingletonHolder.INSTANCE; + } + + private AutopilotControlParameters.AutoPilotLine mAutoPilotLine = null; + private Disposable mSendReqDisposable = null; + + public BusTrajectoryManager() { + mAutoPilotLine = new AutopilotControlParameters.AutoPilotLine(-1, + "", "", "", "", 0, "", + "", "", "", "", 0); + } + + /** + * 同步Bus路线信息 + */ + public void syncTrajectoryInfo() { + BusRoutesResult routesResult = OrderModel.getInstance().getBusRoutesResult(); + if (LoginStatusManager.isLogin() && routesResult != null + && OrderModel.getInstance().getCurrentStationIndex() == 0 + && !OrderModel.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() { + BusRoutesResult routesResult = OrderModel.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(BusConst.LOOP_DELAY, + BusConst.LOOP_PERIOD_10S, TimeUnit.MILLISECONDS) + .map((aLong -> aLong + 1)) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(aLong -> { + if (aLong > BusConst.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"); + + CallerAutoPilotControlManager.INSTANCE.sendTrajectoryDownloadReq(mAutoPilotLine); + CallerLogger.INSTANCE.d(M_BUS + TAG, "sendTrajectoryReq(): " + + GsonUtils.toJson(mAutoPilotLine)); + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/view/BusArcView.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/view/BusArcView.java new file mode 100644 index 0000000000..a9e7bdff5d --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/view/BusArcView.java @@ -0,0 +1,190 @@ +package com.mogo.och.bus.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.bus.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.bus_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.bus_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.bus_ext_arcView_center_text_size)); + + } + + + /** + * 为绘制弧度及数据设置动画 + * + * @param startAngle 开始的弧度 + * @param currentAngle 需要绘制的弧度 + * @param time 动画执行的时长 + */ + private void setAnimation(float startAngle, float currentAngle, int time) { + //绘制当前数据对应的圆弧的动画效果 + ValueAnimator progressAnimator = ValueAnimator.ofFloat(startAngle, currentAngle); + progressAnimator.setDuration(time); + progressAnimator.setTarget(mIncludedAngle); + progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mIncludedAngle = (float) animation.getAnimatedValue(); + //重新绘制,不然不会出现效果 + postInvalidate(); + } + }); + //开始执行动画 + progressAnimator.start(); + } + + + /** + * 设置弧形颜色 + * + * @param value 颜色值 + */ + public void setArcColor(int value) { + mArcColor = value; + } + + /** + * 设置数据 + * + * @param value 当前绘制的值 + */ + public void setValues(int value) { + //完全覆盖 + if (value > maxValue) { + value = maxValue; + } + if (value < 0) { + value = 0; + } + currentValue = value; + //计算弧度比重 + float scale = (float) currentValue / maxValue; + //计算弧度 + float currentAngle = scale * mAngle; + //开始执行动画 + setAnimation(lastAngle, currentAngle, 1000); + lastAngle = currentAngle; + //重新绘制 + postInvalidate(); + } + + + private float dp2px(float dp) { + DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics(); + return dp * metrics.density; + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/view/NoTouchConstraintLayout.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/view/NoTouchConstraintLayout.java new file mode 100644 index 0000000000..558a515bd9 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/view/NoTouchConstraintLayout.java @@ -0,0 +1,37 @@ +package com.mogo.och.bus.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; + +import androidx.constraintlayout.widget.ConstraintLayout; + +import com.mogo.commons.debug.DebugConfig; + +/** + * 强制拦截所有touch时间的约束布局 + * + * @author tongchenfei + */ +public class NoTouchConstraintLayout extends ConstraintLayout { + public NoTouchConstraintLayout(Context context) { + super(context); + } + + public NoTouchConstraintLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public NoTouchConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + if(DebugConfig.isDebug()){ + return super.onInterceptTouchEvent(ev); + }else { + return true; + } + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/view/SlidePanelView.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/view/SlidePanelView.java new file mode 100644 index 0000000000..f04edddbdb --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/view/SlidePanelView.java @@ -0,0 +1,278 @@ +package com.mogo.och.bus.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.commons.AbsMogoApplication; +import com.mogo.eagle.core.utilcode.util.BitmapHelper; +import com.mogo.och.bus.R; + +import me.jessyan.autosize.AutoSizeConfig; +import me.jessyan.autosize.utils.AutoSizeUtils; + +/** + * 滑块滑动面板 + * + * @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 = AutoSizeUtils.dp2px(AbsMogoApplication.getApp(),15); + private static int BLOCK_START_Y = AutoSizeUtils.dp2px(AbsMogoApplication.getApp(),15); + private static int NORMAL_TEXT_MARGIN_LEFT = AutoSizeUtils.dp2px(AbsMogoApplication.getApp(),40); + private static int NORMAL_TEXT_MARGIN_RIGHT = AutoSizeUtils.dp2px(AbsMogoApplication.getApp(),60); + private static int SHORT_TEXT_MARGIN_LEFT = AutoSizeUtils.dp2px(AbsMogoApplication.getApp(),60);; + private static int SHORT_TEXT_MARGIN_RIGHT = AutoSizeUtils.dp2px(AbsMogoApplication.getApp(),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); + int size = AutoSizeUtils.dp2px(getContext(), 120); + BitmapFactory.Options opts = new BitmapFactory.Options(); + opts.inDensity = (int) AutoSizeConfig.getInstance().getInitDensity(); + bmBlock = BitmapFactory.decodeResource(getResources(), R.drawable.bus_base_slide_block,opts); + bmBlock = Bitmap.createScaledBitmap(bmBlock, size, size, true); + blockWidth = bmBlock.getWidth(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int widthMode = MeasureSpec.getMode(widthMeasureSpec); + int heightMode = MeasureSpec.getMode(heightMeasureSpec); + int widthSize; + int heightSize; + + if (blockText.length() < 5) { + textMarginLeft = SHORT_TEXT_MARGIN_LEFT; + textMarginRight = SHORT_TEXT_MARGIN_RIGHT; + } else { + textMarginLeft = NORMAL_TEXT_MARGIN_LEFT; + textMarginRight = NORMAL_TEXT_MARGIN_RIGHT; + } + + if (widthMode == MeasureSpec.AT_MOST) { + // 宽度根据图片大小,字符串长度,各种间隔确定 + // 高度根据图片大小和上下间隔确定 + textPaint.getTextBounds(blockText, 0, blockText.length(), textRect); + widthSize = BLOCK_START_X * 2 + bmBlock.getWidth() + textMarginLeft + textMarginRight + textRect.width(); + heightSize = BLOCK_START_Y * 2 + bmBlock.getHeight(); + widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, widthMode); + heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, heightMode); + } + + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + private float textOffset = 0; + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + if (bgRectF != null){ + bgRectF.left = 0; + bgRectF.top = 0; + bgRectF.right = w; + bgRectF.bottom = h; + } + + if (matrixAnim != null) { + matrixAnim.cancel(); + } + textOffset = (getHeight() - blockTextMetrics.ascent - blockTextMetrics.descent) / 2; + matrixAnim = ObjectAnimator.ofFloat(this, "matrixTranslate", 0, w + GRADIENT_OFFSET).setDuration(2000); + matrixAnim.setRepeatCount(ValueAnimator.INFINITE); + matrixAnim.start(); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (matrixAnim != null) { + matrixAnim.start(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (matrixAnim != null) { + matrixAnim.cancel(); + } + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + float x = event.getX(); + float y = event.getY(); + + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + if (x > BLOCK_START_X + blockOffset && x < blockWidth + BLOCK_START_X + blockOffset && y > BLOCK_START_Y && y < getHeight() - BLOCK_START_Y) { + isToEnd = false; + lastX = x; + } + break; + case MotionEvent.ACTION_MOVE: + if (lastX != 0) { + blockOffset = (int) (x - lastX); + if (blockOffset < 0) { + blockOffset = 0; + } + if (blockOffset + BLOCK_START_X + blockWidth > getWidth()) { + // 超出右边界 + blockOffset = getWidth() - BLOCK_START_X - blockWidth; + if (!isToEnd) { + isToEnd = true; + if (moveToEndListener != null) { + moveToEndListener.moveToEnd(); + } + startBlockBackAnim(); + } + } + invalidate(); + } + break; + case MotionEvent.ACTION_UP: + // 执行滑块回归动画 + if (!isToEnd) { + startBlockBackAnim(); + } + break; + default: + break; + } + + return true; + } + + private void startBlockBackAnim() { + ObjectAnimator blockBackanimator = ObjectAnimator.ofInt(this, "blockOffset", blockOffset, 0); + blockBackanimator.setInterpolator(new DecelerateInterpolator()); + blockBackanimator.setDuration(1000 * blockOffset / getWidth()); + blockBackanimator.start(); + lastX = 0; + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + // 画背景 + canvas.drawRoundRect(bgRectF, (float) getHeight() / 2, (float) getHeight() / 2, bgPaint); + // 画文字 + gradientMatrix.setTranslate(matrixTranslate, 0); + textGradient.setLocalMatrix(gradientMatrix); + canvas.save(); + canvas.drawText(blockText, blockWidth + BLOCK_START_X + textMarginLeft, textOffset, textPaint); + canvas.restore(); + // 画滑块 + canvas.drawBitmap(bmBlock, BLOCK_START_X + blockOffset, BLOCK_START_Y, blockPaint); + } + + public interface OnSlidePanelMoveToEndListener { + /** + * 滑块滑到了末尾 + */ + void moveToEnd(); + } +} diff --git a/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/view/VerticalDashLineView.java b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/view/VerticalDashLineView.java new file mode 100644 index 0000000000..250d4a41b6 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/java/com/mogo/och/bus/view/VerticalDashLineView.java @@ -0,0 +1,64 @@ +package com.mogo.och.bus.view; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.DashPathEffect; +import android.graphics.LinearGradient; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Shader; +import android.util.AttributeSet; +import android.view.View; + +import androidx.annotation.Nullable; + +/** + * 垂直虚线 + * + * @author tongchenfei + */ +public class VerticalDashLineView extends View { + public VerticalDashLineView(Context context) { + this(context,null); + } + + public VerticalDashLineView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs,0); + } + + public VerticalDashLineView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + private final Paint linePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Path dashPath = new Path(); + + private void init(){ + linePaint.setColor(Color.GREEN); + linePaint.setStyle(Paint.Style.STROKE); + linePaint.setStrokeWidth(2); + linePaint.setPathEffect(new DashPathEffect(new float[]{5, 5}, 0)); + } + + public void setGradient(int startColor, int endColor) { + LinearGradient linearGradient = new LinearGradient(0, 0, getWidth(), getHeight(), startColor, endColor, Shader.TileMode.CLAMP); + linePaint.setShader(linearGradient); + invalidate(); + } + + public void setColor(int color) { + linePaint.setShader(null); + linePaint.setColor(color); + invalidate(); + } + + @Override + protected void onDraw(Canvas canvas) { + dashPath.reset(); + dashPath.moveTo((float) getWidth()/2, 0); + dashPath.lineTo((float) getWidth()/2,getHeight()); + canvas.drawPath(dashPath,linePaint); + } +} diff --git a/OCH/mogo-och-shuttle/src/main/res/color/bus_autopilot_text_color_selector.xml b/OCH/mogo-och-shuttle/src/main/res/color/bus_autopilot_text_color_selector.xml new file mode 100644 index 0000000000..15f6897792 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/color/bus_autopilot_text_color_selector.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_base_icon_in_autopilot.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_base_icon_in_autopilot.png new file mode 100644 index 0000000000..75c26c3d71 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_base_icon_in_autopilot.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_base_icon_not_in_autopilot.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_base_icon_not_in_autopilot.png new file mode 100644 index 0000000000..927296d690 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_base_icon_not_in_autopilot.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_base_notice_box_bg.9.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_base_notice_box_bg.9.png new file mode 100644 index 0000000000..8b4b579b56 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_base_notice_box_bg.9.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_base_slide_block.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_base_slide_block.png new file mode 100644 index 0000000000..ed7b293b90 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_base_slide_block.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_disable_autopilot_icon.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_disable_autopilot_icon.png new file mode 100644 index 0000000000..170f254cd1 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_disable_autopilot_icon.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_dot_line.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_dot_line.png new file mode 100644 index 0000000000..186001352c Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_dot_line.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_ic_autopilot.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_ic_autopilot.png new file mode 100644 index 0000000000..be978145dc Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_ic_autopilot.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_icon_arrived_station.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_icon_arrived_station.png new file mode 100644 index 0000000000..8a065b66dd Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_icon_arrived_station.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_icon_arriving_station.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_icon_arriving_station.png new file mode 100644 index 0000000000..4ed57a0e30 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_icon_arriving_station.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_icon_not_arrive_station.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_icon_not_arrive_station.png new file mode 100644 index 0000000000..e0bb24c526 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_icon_not_arrive_station.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_light_green_nor.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_light_green_nor.png new file mode 100644 index 0000000000..bc9fed952d Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_light_green_nor.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_light_red_nor.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_light_red_nor.png new file mode 100644 index 0000000000..8732508ded Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_light_red_nor.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_lightyellow_nor.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_lightyellow_nor.png new file mode 100644 index 0000000000..bae01408fd Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_lightyellow_nor.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_line_panel_bg.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_line_panel_bg.png new file mode 100755 index 0000000000..3166d20e37 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_line_panel_bg.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_line_panel_bg_1.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_line_panel_bg_1.png new file mode 100755 index 0000000000..09a9c252da Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_line_panel_bg_1.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_line_task_arrow.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_line_task_arrow.png new file mode 100644 index 0000000000..b32f0693a6 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_line_task_arrow.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_loading_autopilot_icon.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_loading_autopilot_icon.png new file mode 100644 index 0000000000..f21a1081f1 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_loading_autopilot_icon.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_no_line_icon.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_no_line_icon.png new file mode 100755 index 0000000000..fc20dca73c Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_no_line_icon.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_och_dot_line.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_och_dot_line.png new file mode 100644 index 0000000000..a720a532ea Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_och_dot_line.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_operation_status_bg.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_operation_status_bg.png new file mode 100644 index 0000000000..3c339efde4 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_operation_status_bg.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_operation_status_select_bg.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_operation_status_select_bg.png new file mode 100644 index 0000000000..c6717d2518 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_operation_status_select_bg.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_right_autopilot_icon.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_right_autopilot_icon.png new file mode 100644 index 0000000000..cc2b18083d Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_right_autopilot_icon.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_selected_btn.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_selected_btn.png new file mode 100644 index 0000000000..3f05565483 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_selected_btn.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_setting_btn_bg.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_setting_btn_bg.png new file mode 100644 index 0000000000..ba41bf3a53 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_setting_btn_bg.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_switch_line_close.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_switch_line_close.png new file mode 100644 index 0000000000..370b61de38 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_switch_line_close.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_switch_map_long.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_switch_map_long.png new file mode 100755 index 0000000000..cf3e5a3778 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_switch_map_long.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_switch_map_medium.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_switch_map_medium.png new file mode 100755 index 0000000000..bdc2725468 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_switch_map_medium.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_unselect_btn.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_unselect_btn.png new file mode 100644 index 0000000000..0114bb4f2b Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_unselect_btn.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_wrong_autopilot_icon.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_wrong_autopilot_icon.png new file mode 100644 index 0000000000..0c8988acb3 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/bus_wrong_autopilot_icon.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/end_maker_icon.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/end_maker_icon.png new file mode 100755 index 0000000000..8acf113151 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/end_maker_icon.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_ai_collect.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_ai_collect.png new file mode 100755 index 0000000000..6da7b81fe4 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_ai_collect.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_ai_normal.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_ai_normal.png new file mode 100755 index 0000000000..e98738b192 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_ai_normal.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_ai_select.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_ai_select.png new file mode 100755 index 0000000000..d3e0107c02 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_ai_select.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_arrow_blue_bus.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_arrow_blue_bus.png new file mode 100755 index 0000000000..026c36086f Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_arrow_blue_bus.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_arrow_green_bus.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_arrow_green_bus.png new file mode 100755 index 0000000000..06bebc7013 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_arrow_green_bus.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_arrow_grey_bus.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_arrow_grey_bus.png new file mode 100755 index 0000000000..f4f9b2bca2 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_arrow_grey_bus.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_bad_case.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_bad_case.png new file mode 100755 index 0000000000..22f88301f9 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_bad_case.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_bad_case_normal.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_bad_case_normal.png new file mode 100755 index 0000000000..c0a978fc2b Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_bad_case_normal.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_bad_case_select.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_bad_case_select.png new file mode 100755 index 0000000000..ebacf3a11a Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_bad_case_select.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_no_bus_line.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_no_bus_line.png new file mode 100755 index 0000000000..fc20dca73c Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_no_bus_line.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_point_blue_bus.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_point_blue_bus.png new file mode 100755 index 0000000000..dc4c4f6f0d Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_point_blue_bus.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_point_green_bus.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_point_green_bus.png new file mode 100755 index 0000000000..ed3b871338 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_point_green_bus.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_point_grey_bus.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_point_grey_bus.png new file mode 100755 index 0000000000..d43e34bb26 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_point_grey_bus.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_station_start_end.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_station_start_end.png new file mode 100644 index 0000000000..04580a8f0d Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/icon_station_start_end.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/no_order_data.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/no_order_data.png new file mode 100644 index 0000000000..0e61996d3f Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/no_order_data.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/pingxingjiashi.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/pingxingjiashi.png new file mode 100644 index 0000000000..78bfa2687f Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/pingxingjiashi.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/press_start_status.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/press_start_status.png new file mode 100755 index 0000000000..af32c20cb5 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/press_start_status.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/start_failure.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/start_failure.png new file mode 100755 index 0000000000..5737f93ad8 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/start_failure.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/start_maker_icon.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/start_maker_icon.png new file mode 100644 index 0000000000..9eca61e199 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/start_maker_icon.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/start_success.png b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/start_success.png new file mode 100755 index 0000000000..84246fd323 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable-xhdpi/start_success.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/ai_collect_selector.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/ai_collect_selector.xml new file mode 100755 index 0000000000..a1211f3c47 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/ai_collect_selector.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bad_case_selector.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/bad_case_selector.xml new file mode 100755 index 0000000000..bc47ce95d7 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/bad_case_selector.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bg_bus_traffic_light_background.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/bg_bus_traffic_light_background.xml new file mode 100644 index 0000000000..e0b90b9c55 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/bg_bus_traffic_light_background.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_autopilot_0_1_status_bg.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_autopilot_0_1_status_bg.xml new file mode 100644 index 0000000000..21c3611ffe --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_autopilot_0_1_status_bg.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_autopilot_2_status_bg.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_autopilot_2_status_bg.xml new file mode 100644 index 0000000000..1b95919363 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_autopilot_2_status_bg.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_autopilot_status_bg_check.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_autopilot_status_bg_check.png new file mode 100644 index 0000000000..28857974b5 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_autopilot_status_bg_check.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_autopilot_status_bg_nor.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_autopilot_status_bg_nor.png new file mode 100644 index 0000000000..f7d4f92c4b Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_autopilot_status_bg_nor.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_base_autopilot_status_icon_selector.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_base_autopilot_status_icon_selector.xml new file mode 100644 index 0000000000..94555d78cc --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_base_autopilot_status_icon_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_base_icon_in_autopilot.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_base_icon_in_autopilot.png new file mode 100644 index 0000000000..75c26c3d71 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_base_icon_in_autopilot.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_base_icon_not_in_autopilot.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_base_icon_not_in_autopilot.png new file mode 100644 index 0000000000..927296d690 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_base_icon_not_in_autopilot.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_base_notice_box_bg.9.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_base_notice_box_bg.9.png new file mode 100644 index 0000000000..8b4b579b56 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_base_notice_box_bg.9.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_base_slide_block.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_base_slide_block.png new file mode 100644 index 0000000000..ed7b293b90 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_base_slide_block.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_checkbox_selector.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_checkbox_selector.xml new file mode 100644 index 0000000000..d95e931160 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_checkbox_selector.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_disable_autopilot_icon.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_disable_autopilot_icon.png new file mode 100644 index 0000000000..170f254cd1 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_disable_autopilot_icon.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_dot_line.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_dot_line.png new file mode 100644 index 0000000000..186001352c Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_dot_line.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_ic_autopilot.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_ic_autopilot.png new file mode 100644 index 0000000000..be978145dc Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_ic_autopilot.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_icon_arrived_station.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_icon_arrived_station.png new file mode 100644 index 0000000000..8a065b66dd Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_icon_arrived_station.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_icon_arriving_station.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_icon_arriving_station.png new file mode 100644 index 0000000000..4ed57a0e30 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_icon_arriving_station.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_icon_not_arrive_station.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_icon_not_arrive_station.png new file mode 100644 index 0000000000..e0bb24c526 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_icon_not_arrive_station.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_light_green_nor.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_light_green_nor.png new file mode 100644 index 0000000000..bc9fed952d Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_light_green_nor.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_light_red_nor.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_light_red_nor.png new file mode 100644 index 0000000000..8732508ded Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_light_red_nor.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_lightyellow_nor.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_lightyellow_nor.png new file mode 100644 index 0000000000..bae01408fd Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_lightyellow_nor.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_line_dividing_line1_selector.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_line_dividing_line1_selector.xml new file mode 100644 index 0000000000..b00fbd8bd6 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_line_dividing_line1_selector.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_line_dividing_line2_selector.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_line_dividing_line2_selector.xml new file mode 100644 index 0000000000..ee555aae15 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_line_dividing_line2_selector.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_line_panel_bg.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_line_panel_bg.png new file mode 100755 index 0000000000..3166d20e37 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_line_panel_bg.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_line_panel_bg_1.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_line_panel_bg_1.png new file mode 100755 index 0000000000..09a9c252da Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_line_panel_bg_1.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_loading_autopilot_icon.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_loading_autopilot_icon.png new file mode 100644 index 0000000000..f21a1081f1 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_loading_autopilot_icon.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_och_dot_line.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_och_dot_line.png new file mode 100644 index 0000000000..a720a532ea Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_och_dot_line.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_operation_status_bg_selector.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_operation_status_bg_selector.xml new file mode 100755 index 0000000000..3a3dc6a292 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_operation_status_bg_selector.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_panel_anchor_bkg.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_panel_anchor_bkg.xml new file mode 100644 index 0000000000..21b39b7e37 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_panel_anchor_bkg.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_panel_bkg.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_panel_bkg.xml new file mode 100644 index 0000000000..69539ed40f --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_panel_bkg.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_right_autopilot_icon.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_right_autopilot_icon.png new file mode 100644 index 0000000000..cc2b18083d Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_right_autopilot_icon.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_selected_btn.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_selected_btn.png new file mode 100644 index 0000000000..3f05565483 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_selected_btn.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_setting_btn_bg.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_setting_btn_bg.png new file mode 100644 index 0000000000..ba41bf3a53 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_setting_btn_bg.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_setting_tip_red_cir_bg.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_setting_tip_red_cir_bg.xml new file mode 100644 index 0000000000..203971340e --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_setting_tip_red_cir_bg.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_shape_select_line_item_bg_normal.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_shape_select_line_item_bg_normal.xml new file mode 100644 index 0000000000..272e718cce --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_shape_select_line_item_bg_normal.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_shape_select_line_item_bg_selected.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_shape_select_line_item_bg_selected.xml new file mode 100644 index 0000000000..e5faafb27b --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_shape_select_line_item_bg_selected.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_shape_select_line_item_time_bg.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_shape_select_line_item_time_bg.xml new file mode 100644 index 0000000000..ee8088637c --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_shape_select_line_item_time_bg.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_shape_select_line_item_time_bg_selected.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_shape_select_line_item_time_bg_selected.xml new file mode 100644 index 0000000000..e2b482ee5f --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_shape_select_line_item_time_bg_selected.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_station_green_dash_line.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_station_green_dash_line.xml new file mode 100644 index 0000000000..fe46ef2228 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_station_green_dash_line.xml @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_station_v_green_dash.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_station_v_green_dash.xml new file mode 100644 index 0000000000..376e0a472c --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_station_v_green_dash.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_switch_line_btn.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_switch_line_btn.xml new file mode 100644 index 0000000000..8b066b0ce8 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_switch_line_btn.xml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_switch_line_btn_commit.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_switch_line_btn_commit.xml new file mode 100644 index 0000000000..e94992d507 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_switch_line_btn_commit.xml @@ -0,0 +1,10 @@ + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_switch_line_close.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_switch_line_close.png new file mode 100644 index 0000000000..370b61de38 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_switch_line_close.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_switch_map_bg.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_switch_map_bg.xml new file mode 100644 index 0000000000..b34021d977 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_switch_map_bg.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_switch_map_long.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_switch_map_long.png new file mode 100755 index 0000000000..cf3e5a3778 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_switch_map_long.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_switch_map_medium.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_switch_map_medium.png new file mode 100755 index 0000000000..bdc2725468 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_switch_map_medium.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_task_time_bg.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_task_time_bg.xml new file mode 100644 index 0000000000..917f3932fe --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_task_time_bg.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_unselect_btn.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_unselect_btn.png new file mode 100644 index 0000000000..0114bb4f2b Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_unselect_btn.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_wrong_autopilot_icon.png b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_wrong_autopilot_icon.png new file mode 100644 index 0000000000..0c8988acb3 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_wrong_autopilot_icon.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_yi_biao_pan_bg_nor.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_yi_biao_pan_bg_nor.xml new file mode 100644 index 0000000000..2ef90e60f7 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_yi_biao_pan_bg_nor.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/bus_yi_biao_pan_bg_speeding.xml b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_yi_biao_pan_bg_speeding.xml new file mode 100644 index 0000000000..dea7a88bb6 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/drawable/bus_yi_biao_pan_bg_speeding.xml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/end_maker_icon.png b/OCH/mogo-och-shuttle/src/main/res/drawable/end_maker_icon.png new file mode 100755 index 0000000000..8acf113151 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/end_maker_icon.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/icon_ai_normal.png b/OCH/mogo-och-shuttle/src/main/res/drawable/icon_ai_normal.png new file mode 100755 index 0000000000..e98738b192 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/icon_ai_normal.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/icon_ai_select.png b/OCH/mogo-och-shuttle/src/main/res/drawable/icon_ai_select.png new file mode 100755 index 0000000000..d3e0107c02 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/icon_ai_select.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/icon_arrow_blue_bus.png b/OCH/mogo-och-shuttle/src/main/res/drawable/icon_arrow_blue_bus.png new file mode 100755 index 0000000000..026c36086f Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/icon_arrow_blue_bus.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/icon_arrow_green_bus.png b/OCH/mogo-och-shuttle/src/main/res/drawable/icon_arrow_green_bus.png new file mode 100755 index 0000000000..06bebc7013 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/icon_arrow_green_bus.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/icon_arrow_grey_bus.png b/OCH/mogo-och-shuttle/src/main/res/drawable/icon_arrow_grey_bus.png new file mode 100755 index 0000000000..f4f9b2bca2 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/icon_arrow_grey_bus.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/icon_bad_case_normal.png b/OCH/mogo-och-shuttle/src/main/res/drawable/icon_bad_case_normal.png new file mode 100755 index 0000000000..c0a978fc2b Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/icon_bad_case_normal.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/icon_bad_case_select.png b/OCH/mogo-och-shuttle/src/main/res/drawable/icon_bad_case_select.png new file mode 100755 index 0000000000..ebacf3a11a Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/icon_bad_case_select.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/icon_no_bus_line.png b/OCH/mogo-och-shuttle/src/main/res/drawable/icon_no_bus_line.png new file mode 100755 index 0000000000..fc20dca73c Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/icon_no_bus_line.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/icon_point_blue_bus.png b/OCH/mogo-och-shuttle/src/main/res/drawable/icon_point_blue_bus.png new file mode 100755 index 0000000000..dc4c4f6f0d Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/icon_point_blue_bus.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/icon_point_green_bus.png b/OCH/mogo-och-shuttle/src/main/res/drawable/icon_point_green_bus.png new file mode 100755 index 0000000000..ed3b871338 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/icon_point_green_bus.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/icon_point_grey_bus.png b/OCH/mogo-och-shuttle/src/main/res/drawable/icon_point_grey_bus.png new file mode 100755 index 0000000000..d43e34bb26 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/icon_point_grey_bus.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/icon_station_start_end.png b/OCH/mogo-och-shuttle/src/main/res/drawable/icon_station_start_end.png new file mode 100644 index 0000000000..04580a8f0d Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/icon_station_start_end.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/no_order_data.png b/OCH/mogo-och-shuttle/src/main/res/drawable/no_order_data.png new file mode 100644 index 0000000000..0e61996d3f Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/no_order_data.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/press_start_status.png b/OCH/mogo-och-shuttle/src/main/res/drawable/press_start_status.png new file mode 100755 index 0000000000..af32c20cb5 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/press_start_status.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/start_failure.png b/OCH/mogo-och-shuttle/src/main/res/drawable/start_failure.png new file mode 100755 index 0000000000..5737f93ad8 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/start_failure.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/start_maker_icon.png b/OCH/mogo-och-shuttle/src/main/res/drawable/start_maker_icon.png new file mode 100644 index 0000000000..9eca61e199 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/start_maker_icon.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/drawable/start_success.png b/OCH/mogo-och-shuttle/src/main/res/drawable/start_success.png new file mode 100755 index 0000000000..84246fd323 Binary files /dev/null and b/OCH/mogo-och-shuttle/src/main/res/drawable/start_success.png differ diff --git a/OCH/mogo-och-shuttle/src/main/res/layout/activity_bus_switch_line.xml b/OCH/mogo-och-shuttle/src/main/res/layout/activity_bus_switch_line.xml new file mode 100644 index 0000000000..703490ed83 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/layout/activity_bus_switch_line.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OCH/mogo-och-shuttle/src/main/res/layout/bus_base_fragment.xml b/OCH/mogo-och-shuttle/src/main/res/layout/bus_base_fragment.xml new file mode 100644 index 0000000000..04f8739e01 --- /dev/null +++ b/OCH/mogo-och-shuttle/src/main/res/layout/bus_base_fragment.xml @@ -0,0 +1,417 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +