diff --git a/OCH/shuttle_weaknet/driver/.gitignore b/OCH/shuttle_weaknet/driver/.gitignore
new file mode 100644
index 0000000000..42afabfd2a
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/build.gradle b/OCH/shuttle_weaknet/driver/build.gradle
new file mode 100644
index 0000000000..9d0078f8e6
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/build.gradle
@@ -0,0 +1,69 @@
+apply plugin: 'com.android.library'
+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", "shuttle"+project.getName())
+ }
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ lintOptions {
+ abortOnError false
+ }
+
+ 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.kotlinstdlib
+ implementation rootProject.ext.dependencies.androidxappcompat
+ implementation rootProject.ext.dependencies.arouter
+ kapt 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:common:common")
+ implementation project(":OCH:common:data")
+ 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/shuttle_weaknet/driver/consumer-rules.pro b/OCH/shuttle_weaknet/driver/consumer-rules.pro
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/OCH/shuttle_weaknet/driver/gradle.properties b/OCH/shuttle_weaknet/driver/gradle.properties
new file mode 100644
index 0000000000..dd5c44ee62
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/gradle.properties
@@ -0,0 +1,3 @@
+GROUP=com.mogo.och
+POM_ARTIFACT_ID=och-bus
+VERSION_CODE=1
diff --git a/OCH/shuttle_weaknet/driver/proguard-rules.pro b/OCH/shuttle_weaknet/driver/proguard-rules.pro
new file mode 100644
index 0000000000..481bb43481
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/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/shuttle_weaknet/driver/src/main/AndroidManifest.xml b/OCH/shuttle_weaknet/driver/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..b24b4d5534
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/AndroidManifest.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ShuttleDriverProvider.kt b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ShuttleDriverProvider.kt
new file mode 100644
index 0000000000..ff8e351db4
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ShuttleDriverProvider.kt
@@ -0,0 +1,38 @@
+package com.mogo.och.shuttle
+
+import android.content.Context
+import androidx.fragment.app.Fragment
+import com.alibaba.android.arouter.facade.annotation.Route
+import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d
+import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
+import com.mogo.och.shuttle.fragment.ShuttleFragment
+import com.mogo.och.common.module.constant.OchCommonConst
+import com.mogo.och.common.module.biz.provider.CommonServiceImpl
+
+/**
+ * 网约车小巴业务实现入口
+ *
+ * @author tongchenfei
+ */
+@Route(path = OchCommonConst.SHUTTLE_DRIVER)
+class ShuttleDriverProvider : CommonServiceImpl() {
+
+ private val TAG = ShuttleDriverProvider::class.java.simpleName
+ private var busFragment: ShuttleFragment?=null
+
+ override fun init(context: Context) {
+ d(SceneConstant.M_TAXI + TAG, "init")
+ }
+
+ override fun getFragment(): Fragment {
+ if(busFragment==null){
+ busFragment = ShuttleFragment()
+ }
+ return busFragment!!
+ }
+
+ override fun resetFragment() {
+ busFragment = null
+ }
+
+}
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusCloseTaskRequest.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusCloseTaskRequest.java
new file mode 100644
index 0000000000..7854aa0e07
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusCloseTaskRequest.java
@@ -0,0 +1,23 @@
+package com.mogo.och.shuttle.bean;
+
+import com.mogo.commons.storage.SharedPrefsMgr;
+import com.mogo.och.common.module.utils.DateTimeUtil;
+
+/**
+ * 中止/结束任务请求
+ */
+public class BusCloseTaskRequest {
+
+ private String sn;
+ private int taskId;
+ private long writeVersion;
+ public BusCloseTaskRequest(int taskId) {
+ this.sn = SharedPrefsMgr.getInstance().getSn();
+ this.taskId = taskId;
+ this.writeVersion = DateTimeUtil.getCurrentTimeStamp();
+ }
+
+ public String getSn() {
+ return sn;
+ }
+}
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusOrderBean.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusOrderBean.java
new file mode 100644
index 0000000000..4a4230ccd6
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusOrderBean.java
@@ -0,0 +1,86 @@
+package com.mogo.och.shuttle.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/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusOrdersResponse.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusOrdersResponse.java
new file mode 100644
index 0000000000..03a2b23b96
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusOrdersResponse.java
@@ -0,0 +1,23 @@
+package com.mogo.och.shuttle.bean;
+
+import com.mogo.eagle.core.data.BaseData;
+
+import java.util.List;
+
+/**
+ * @author: wangmingjun
+ * @date: 2021/10/19
+ */
+public class BusOrdersResponse extends BaseData {
+ public Result data;
+ public static class Result{
+ public List orders;
+ }
+
+ @Override
+ public String toString() {
+ return "BusOrdersResponse{" +
+ "data=" + data +
+ '}';
+ }
+}
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusQueryLineStationsRequest.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusQueryLineStationsRequest.java
new file mode 100644
index 0000000000..0f3cd777ea
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusQueryLineStationsRequest.java
@@ -0,0 +1,17 @@
+package com.mogo.och.shuttle.bean;
+
+import com.mogo.commons.storage.SharedPrefsMgr;
+
+/**
+ * @author congtaowang
+ * @since 2021/3/22
+ *
+ * 根据车机行驶线路站点信息
+ */
+public class BusQueryLineStationsRequest {
+
+ private String sn;
+ public BusQueryLineStationsRequest() {
+ this.sn = SharedPrefsMgr.getInstance().getSn();
+ }
+}
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusQueryLineTaskResponse.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusQueryLineTaskResponse.java
new file mode 100644
index 0000000000..fbf8f22c3b
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusQueryLineTaskResponse.java
@@ -0,0 +1,19 @@
+package com.mogo.och.shuttle.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/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusQueryLinesResponse.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusQueryLinesResponse.java
new file mode 100644
index 0000000000..a5ad54daa8
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusQueryLinesResponse.java
@@ -0,0 +1,27 @@
+package com.mogo.och.shuttle.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/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusResetDrivingLineRequest.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusResetDrivingLineRequest.java
new file mode 100644
index 0000000000..ef6cdbda93
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusResetDrivingLineRequest.java
@@ -0,0 +1,20 @@
+package com.mogo.och.shuttle.bean;
+
+import com.mogo.commons.storage.SharedPrefsMgr;
+import com.mogo.och.common.module.utils.DateTimeUtil;
+
+/**
+ * @author: wangmingjun
+ * @date: 2021/10/18
+ */
+public class BusResetDrivingLineRequest {
+ public String sn;
+ public int taskId; //切换到的线路id
+ public long writeVersion; //更新时间戳
+
+ public BusResetDrivingLineRequest(int taskId) {
+ this.sn = SharedPrefsMgr.getInstance().getSn();
+ this.taskId = taskId;
+ this.writeVersion = DateTimeUtil.getCurrentTimeStamp();
+ }
+}
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusRoutesResponse.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusRoutesResponse.java
new file mode 100644
index 0000000000..667135077b
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusRoutesResponse.java
@@ -0,0 +1,28 @@
+package com.mogo.och.shuttle.bean;
+
+import com.mogo.eagle.core.data.BaseData;
+import com.mogo.och.data.bean.BusRoutesResult;
+
+/**
+ * 网约车小巴路线接口请求响应结果
+ *
+ * @author tongchenfei
+ */
+public 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 +
+ '}';
+ }
+}
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusUpdateSiteStatusRequest.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusUpdateSiteStatusRequest.java
new file mode 100644
index 0000000000..13ba2e4f3c
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/BusUpdateSiteStatusRequest.java
@@ -0,0 +1,26 @@
+package com.mogo.och.shuttle.bean;
+
+import com.mogo.commons.storage.SharedPrefsMgr;
+
+/**
+ * @author congtaowang
+ * @since 2021/3/22
+ *
+ * 小巴车运营状态请求参数
+ */
+public class BusUpdateSiteStatusRequest {
+
+ public String sn;
+ public int taskId;
+ public int seq;//站点序号
+ public int siteId;//站点id
+ public long writeVersion; //更新时间戳
+
+ public BusUpdateSiteStatusRequest(int taskId,int siteId,int seq, long writeVersion) {
+ this.sn = SharedPrefsMgr.getInstance().getSn();
+ this.seq = seq;
+ this.siteId = siteId;
+ this.taskId = taskId;
+ this.writeVersion = writeVersion;
+ }
+}
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/QueryLeaveAwayPassengersRequest.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/QueryLeaveAwayPassengersRequest.java
new file mode 100644
index 0000000000..8c13428bff
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/QueryLeaveAwayPassengersRequest.java
@@ -0,0 +1,36 @@
+package com.mogo.och.shuttle.bean;
+
+import com.mogo.commons.storage.SharedPrefsMgr;
+
+/**
+ * 查询下车乘客请求参数
+ *
+ * @author tongchenfei
+ */
+public class QueryLeaveAwayPassengersRequest {
+ private String sn;
+ private int seq; //站点在线路中的序号
+ private int siteId; //站点id
+
+ public QueryLeaveAwayPassengersRequest(int seq, int siteId) {
+ this.sn = SharedPrefsMgr.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/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/QueryLeaveAwayPassengersResponse.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/QueryLeaveAwayPassengersResponse.java
new file mode 100644
index 0000000000..b11ba9329b
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/QueryLeaveAwayPassengersResponse.java
@@ -0,0 +1,60 @@
+package com.mogo.och.shuttle.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/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/WriteOffCountResponse.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/WriteOffCountResponse.java
new file mode 100644
index 0000000000..b8eaa7e68d
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/WriteOffCountResponse.java
@@ -0,0 +1,15 @@
+package com.mogo.och.shuttle.bean;
+
+import com.mogo.eagle.core.data.BaseData;
+
+import java.util.List;
+
+/**
+ * @author: wangmingjun
+ * @date: 2022/2/9
+ */
+public class WriteOffCountResponse extends BaseData {
+
+ public Integer data;
+
+}
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/WriteOffPassenger.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/WriteOffPassenger.java
new file mode 100644
index 0000000000..624c296d9f
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/bean/WriteOffPassenger.java
@@ -0,0 +1,15 @@
+package com.mogo.och.shuttle.bean;
+
+import java.io.Serializable;
+
+/**
+ * @author: wangmingjun
+ * @date: 2022/9/23
+ */
+public class WriteOffPassenger implements Serializable {
+ public String phone;
+ public String orderNo;
+ public String ticketName;
+ public int passengerSize;
+ public long writeOffTime;
+}
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/callback/IBusADASStatusCallback.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/callback/IBusADASStatusCallback.java
new file mode 100644
index 0000000000..8a59bcb206
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/callback/IBusADASStatusCallback.java
@@ -0,0 +1,11 @@
+package com.mogo.och.shuttle.callback;
+
+/**
+ * Created on 2021/9/8
+ *
+ * Model->Presenter回调:ADAS相关(自动驾驶状态回调,到达终点等等)
+ */
+public interface IBusADASStatusCallback {
+ //自驾返回失败
+ void onStartAdasFailure();
+}
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/callback/IBusControllerStatusCallback.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/callback/IBusControllerStatusCallback.java
new file mode 100644
index 0000000000..2e3a71fff3
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/callback/IBusControllerStatusCallback.java
@@ -0,0 +1,15 @@
+package com.mogo.och.shuttle.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 {
+ // 自车定位
+ void onCarLocationChanged(MogoLocation location);
+ //开始开启自动驾驶
+ void startOpenAutopilot();
+}
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/callback/IBusLinesCallback.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/callback/IBusLinesCallback.java
new file mode 100644
index 0000000000..f52a9c7454
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/callback/IBusLinesCallback.java
@@ -0,0 +1,14 @@
+package com.mogo.och.shuttle.callback;
+
+import com.mogo.och.shuttle.bean.BusQueryLineTaskResponse;
+import com.mogo.och.shuttle.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/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/callback/IRefreshBusStationsCallback.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/callback/IRefreshBusStationsCallback.java
new file mode 100644
index 0000000000..14e30a34fa
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/callback/IRefreshBusStationsCallback.java
@@ -0,0 +1,23 @@
+package com.mogo.och.shuttle.callback;
+
+import com.mogo.och.data.bean.BusStationBean;
+
+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/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/callback/ISlidePannelHideCallback.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/callback/ISlidePannelHideCallback.java
new file mode 100644
index 0000000000..6acad8a540
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/callback/ISlidePannelHideCallback.java
@@ -0,0 +1,9 @@
+package com.mogo.och.shuttle.callback;
+
+/**
+ * @author: wangmingjun
+ * @date: 2021/10/22
+ */
+public interface ISlidePannelHideCallback {
+ void hideSlidePanel();
+}
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/constant/BusConst.kt b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/constant/BusConst.kt
new file mode 100644
index 0000000000..10fb756a69
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/constant/BusConst.kt
@@ -0,0 +1,60 @@
+package com.mogo.och.shuttle.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";
+
+
+ /**
+ * 订单起终点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/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/fragment/BaseShuttleTabFragment.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/fragment/BaseShuttleTabFragment.java
new file mode 100644
index 0000000000..6043c194ec
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/fragment/BaseShuttleTabFragment.java
@@ -0,0 +1,558 @@
+package com.mogo.och.shuttle.fragment;
+
+import static com.mogo.och.shuttle.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.RelativeLayout;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.constraintlayout.widget.Group;
+import androidx.core.content.ContextCompat;
+
+import com.mogo.commons.AbsMogoApplication;
+import com.mogo.commons.mvp.IView;
+import com.mogo.commons.mvp.MvpFragment;
+import com.mogo.commons.mvp.Presenter;
+import com.mogo.eagle.core.data.config.FunctionBuildConfig;
+import com.mogo.eagle.core.data.config.HdMapBuildConfig;
+import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener;
+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.CallerAutopilotRecordListenerManager;
+import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager;
+import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager;
+import com.mogo.eagle.core.function.hmi.ui.msgbox.DriverMsgBoxBubbleView;
+import com.mogo.eagle.core.function.hmi.ui.msgbox.DriverMsgBoxButtonView;
+import com.mogo.eagle.core.function.hmi.ui.msgbox.DriverMsgBoxListView;
+import com.mogo.eagle.core.function.smp.view.SmallMapView;
+import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils;
+import com.mogo.eagle.core.utilcode.mogo.view.OnPreventFastClickListener;
+import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
+import com.mogo.map.MogoMap;
+import com.mogo.map.uicontroller.IMogoMapUIController;
+import com.mogo.och.common.module.utils.ResourcesUtils;
+import com.mogo.och.shuttle.R;
+import com.mogo.och.shuttle.view.BizMapView;
+import com.mogo.och.data.bean.BusRoutesResult;
+import com.mogo.och.shuttle.model.OrderModel;
+import com.mogo.och.shuttle.view.SlidePanelView;
+import com.mogo.och.common.module.utils.SoundPoolHelper;
+
+import org.greenrobot.eventbus.EventBus;
+/**
+ * 网约车基础Fragment,主要负责布局通用界面,处理站点面板和通话面板互斥情况
+ *
+ * 部分业务放在了此处处理
+ *
+ * @author tongchenfei
+ */
+public abstract class BaseShuttleTabFragment> extends MvpFragment {
+
+ private static final String TAG = "BaseBusTabFragment";
+
+ protected SlidePanelView slidePanelView;
+ private RelativeLayout ctvAutopilotStatus;
+ private ImageView ctvAutopilotStatusIv;
+ private TextView ctvAutopilotStatusTv;
+ protected TextView tvArrived;
+ private FrameLayout flStationPanelContainer;
+ private BizMapView mapBizView;
+ private Group groupTestPanel;
+
+ 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.shuttle_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);
+
+ tvArrived = findViewById(R.id.module_mogo_och_arrived_tv);
+
+ FrameLayout flSpeed = findViewById(R.id.fl_speed);
+ if (flSpeed != null) {
+ CallerDevaToolsManager.INSTANCE.attachAutopilotBeforeLaunchView(flSpeed.getContext(), flSpeed);
+ }
+
+ LayoutInflater.from(getContext()).inflate(getStationPanelViewId(), flStationPanelContainer);
+ slidePanelView.setOnSlidePanelMoveToEndListener(onSlideToEndListener);
+
+ updateSwitchMapIcon();
+
+ initListener();
+ setAutopilotBtnStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getState(),
+ CallerAutoPilotControlManager.INSTANCE.isCanStartAutopilot(false, 0));
+ 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()
+ );
+
+ tvArrived.setOnClickListener(view -> {
+ onArriveStation();
+ });
+
+ //消息盒子
+ 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 mapUIController = CallerMapUIServiceManager.INSTANCE.getMapUIController(MogoMap.DEFAULT);
+ if(mapUIController!=null){
+ if (AppIdentityModeUtils.isB2(FunctionBuildConfig.appIdentityMode)) {
+ mapUIController.changeCurrentIcon(R.raw.m2);
+ HdMapBuildConfig.currentCarVrIconRes = R.raw.m2;
+ }else if (AppIdentityModeUtils.isB1(FunctionBuildConfig.appIdentityMode)) {
+ mapUIController.changeCurrentIcon(R.raw.xiaoba);
+ HdMapBuildConfig.currentCarVrIconRes = R.raw.xiaoba;
+ }
+ }
+ }
+
+ @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();
+ if(smallMapView != null){
+ smallMapView.onDestroy();
+ }
+ super.onDestroyView();
+ CallerAutopilotRecordListenerManager.INSTANCE.removeListener(TAG);
+ EventBus.getDefault().unregister(this);
+ }
+
+ /**
+ * 测试到站
+ */
+ protected abstract void debugArrivedStation();
+
+ private void initListener() {
+
+ }
+
+ /**
+ * 展示滑动按钮
+ *
+ * @param text 指定的文字
+ */
+ public void showSlidePanel(String text) {
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ slidePanelView.setText(text);
+ slidePanelView.setVisibility(View.VISIBLE);
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+ setArrivedClikable(false);
+ }
+
+ /**
+ * 设置进站按钮状态
+ *
+ * @param isClickable
+ */
+ public void setArrivedClikable(boolean isClickable) {
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ tvArrived.setEnabled(isClickable);
+ if (isClickable) {
+ tvArrived.setTextColor(ContextCompat.getColor(AbsMogoApplication.getApp(),R.color.bus_white));
+ } else {
+ tvArrived.setTextColor(ContextCompat.getColor(AbsMogoApplication.getApp(),R.color.bus_arrived_btn_un_clickable_color));
+ }
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+ }
+
+ /**
+ * 隐藏滑动按钮
+ */
+ public void hideSlidePanel() {
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ slidePanelView.setVisibility(View.GONE);
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+ }
+
+ public void playDI() {
+ SoundPoolHelper.getSoundPoolHelper().playSoundWithRedId(getContext(), R.raw.bus_di);
+ }
+
+ /**
+ * 改变自动驾驶状态
+ *
+ * @param autopilotStatus 0:不可用 1:可用状态 2:自动驾驶中
+ */
+ public void onAutopilotStatusChanged(int autopilotStatus,boolean canStartAuto) {
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ changeAutopilotBtnView(autopilotStatus, isAnimateRunning,canStartAuto);
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+ }
+
+ public void setAutopilotBtnStatus(int autopilotStatus,boolean canStartAuto) {
+ if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE == autopilotStatus) {//0不可用
+ ctvAutopilotStatusTv.setTextColor(ResourcesUtils.getColor(R.color.bus_autopilot_text_color_disable));
+ ctvAutopilotStatusTv.setText(ResourcesUtils.getString(R.string.bus_loading_autopilot_runnig_tv));
+ ctvAutopilotStatusIv.setImageResource(R.drawable.bus_disable_autopilot_icon);
+ ctvAutopilotStatus.setClickable(true);
+ ctvAutopilotStatus.setBackgroundResource(R.drawable.common_autopilot_start_fail);
+ } else {
+ ctvAutopilotStatusTv.setTextColor(AbsMogoApplication.getApp().getColor(R.color.bus_autopilot_text_color_normal));
+ ctvAutopilotStatusIv.setImageResource(R.drawable.bus_ic_autopilot);
+ if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE == autopilotStatus) { //1可用
+ ctvAutopilotStatusTv.setText(ResourcesUtils.getString(R.string.bus_loading_autopilot_runnig_tv));
+ if(canStartAuto){
+ ctvAutopilotStatus.setClickable(true);
+ ctvAutopilotStatus.setBackgroundResource(R.drawable.common_autopilot_press);
+ }else {
+ ctvAutopilotStatusTv.setTextColor(ResourcesUtils.getColor(R.color.bus_autopilot_text_color_disable));
+ ctvAutopilotStatusIv.setImageResource(R.drawable.bus_disable_autopilot_icon);
+ ctvAutopilotStatus.setClickable(true);
+ ctvAutopilotStatus.setBackgroundResource(R.drawable.common_autopilot_start_fail);
+ }
+ } else if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING == autopilotStatus) {
+ ctvAutopilotStatusTv.setText(R.string.bus_loading_autopilot_runnig_tv);
+ ctvAutopilotStatus.setClickable(true);
+ ctvAutopilotStatus.setBackgroundResource(R.drawable.common_autopilot_in_autopilot);
+ } else if (IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING
+ == autopilotStatus){
+ ctvAutopilotStatusTv.setText(R.string.bus_pingxing_driver);
+ ctvAutopilotStatus.setClickable(false);
+ ctvAutopilotStatus.setBackgroundResource(R.drawable.common_autopilot_pxjs);
+ }
+ }
+ }
+
+ public void updateAutopilotStatus(int autopilotStatus) {
+ if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING
+ == autopilotStatus) {//2 running
+ ctvAutopilotStatusIv.setImageResource(R.drawable.bus_right_autopilot_icon);
+ ctvAutopilotStatusTv.setTextColor(ResourcesUtils.getColor(R.color.bus_autopilot_text_color_normal));
+ ctvAutopilotStatusTv.setText(ResourcesUtils.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(ResourcesUtils.getColor(R.color.bus_autopilot_text_color_normal));
+ ctvAutopilotStatusTv.setText(ResourcesUtils.getString(R.string.bus_loading_autopilot_failure_tv));
+ ctvAutopilotStatus.setClickable(false);
+// ctvAutopilotStatus.setSelected(false);
+ }
+ UiThreadHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ setAutopilotBtnStatus(autopilotStatus,CallerAutoPilotControlManager.INSTANCE.isCanStartAutopilot(false, 0));
+ }
+ }, 1000);
+ }
+
+ private void changeAutopilotBtnView(int autopilotStatus, boolean isAnimateRunning,boolean canStartAuto) {
+ if (isAnimateRunning && IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING
+ != autopilotStatus) {
+ // 主动开启自动驾驶中,不为2(为0、1)则继续loading
+ return;
+ }
+ if (isAnimateRunning) {
+ stopAnimAndUpdateBtnStatus();
+ } else {
+ setAutopilotBtnStatus(autopilotStatus,canStartAuto);
+ }
+
+ }
+
+ public void stopAnimAndUpdateBtnStatus() {
+ stopAutopilotAnimation();
+ updateAutopilotStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getState());
+ }
+
+ /**
+ * 隐藏【自动驾驶】按钮
+ */
+ public void hideAutopilotBiz() {
+ }
+
+ /**
+ * 展示【自动驾驶】按钮
+ */
+ public void showAutopilotBiz() {
+ }
+
+ 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(ResourcesUtils.getString(R.string.bus_loading_autopilot_tv));
+ ctvAutopilotStatusTv.setTextColor(ResourcesUtils.getColor(R.color.bus_autopilot_text_color_normal));
+ 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.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();
+ }
+
+ /**
+ * 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 lineNameTV;
+ 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);
+ lineNameTV = findViewById(R.id.bus_test_bar_current_line_name);
+ 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())));
+ lineNameTV.setText("lineName:" + (routesResult == null ? "" : routesResult.getName()));
+ 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())));
+ lineNameTV.setText("lineName:" + (routesResult == null ? "" : routesResult.getName()));
+ 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/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/fragment/ShuttleFragment.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/fragment/ShuttleFragment.java
new file mode 100644
index 0000000000..3ff99861e0
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/fragment/ShuttleFragment.java
@@ -0,0 +1,551 @@
+package com.mogo.och.shuttle.fragment;
+
+import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS;
+import static com.mogo.map.MogoMap.DEFAULT;
+
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+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.mogo.commons.storage.SharedPrefsMgr;
+import com.mogo.eagle.core.data.config.FunctionBuildConfig;
+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.ActivityUtils;
+import com.mogo.eagle.core.utilcode.util.ToastUtils;
+import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
+import com.mogo.map.overlay.IMoGoOverlayManager;
+import com.mogo.map.overlay.core.Level;
+import com.mogo.map.overlay.point.Point;
+import com.mogo.och.common.module.utils.ResourcesUtils;
+import com.mogo.och.shuttle.R;
+import com.mogo.och.data.bean.BusStationBean;
+import com.mogo.och.shuttle.constant.BusConst;
+import com.mogo.och.shuttle.presenter.BusPresenter;
+import com.mogo.och.shuttle.ui.BusStationCommonItem;
+import com.mogo.och.shuttle.ui.BusSwitchLineActivity;
+import com.mogo.och.shuttle.view.SlidePanelView;
+import com.mogo.och.common.module.utils.BlinkAnimationUtil;
+import com.mogo.och.common.module.utils.OCHThreadPoolManager;
+import com.mogo.och.common.module.utils.QRUtilsKt;
+import com.mogo.och.common.module.wigets.BindQRCodeDialog;
+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;
+
+import me.jessyan.autosize.utils.AutoSizeUtils;
+
+
+/**
+ * 网约车小巴界面
+ *
+ * @author tongchenfei
+ */
+public class ShuttleFragment extends BaseShuttleTabFragment
+ 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;
+
+
+ @Override
+ public String getTagName() {
+ return "BusFragment";
+ }
+
+ @Override
+ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ }
+ @Override
+ public void onDestroyView() {
+ if (mPresenter != null) {
+ mPresenter.onDestroy(this);
+ }
+ IMoGoOverlayManager overlayManager = CallerMapUIServiceManager.INSTANCE.getOverlayManager();
+ if(overlayManager!=null) {
+ overlayManager.removeAllLines();
+ overlayManager.removeAllPoints();
+ }
+ super.onDestroyView();
+ }
+
+ @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.d(M_BUS + TAG, "initView: " + CallerAutoPilotStatusListenerManager.INSTANCE.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.d(M_BUS + TAG,"changeOverview Event消息去登出");
+ mPresenter.logout();
+ }else if (eventLogout.getMessgae() == EventLogout.SHOW_QR_TYPE){ //显示二维码
+ CallerLogger.d(M_BUS + TAG,"changeOverview Event qrcode,sn = "
+ + SharedPrefsMgr.getInstance().getSn());
+ String qrUrl = String.format(FunctionBuildConfig.urlJson.getBindDriverQRUrl(),
+ SharedPrefsMgr.getInstance().getSn());
+ Bitmap bmQr = QRUtilsKt.createQRCodeWithPicture(
+ BitmapFactory.decodeResource(getResources(), R.drawable.icon_qr_center_logo)
+ ,qrUrl, AutoSizeUtils.dp2px(getContext(),340f),
+ AutoSizeUtils.dp2px(getContext(),340f),true);
+ if (bmQr != null){
+ BindQRCodeDialog.Builder builder = new BindQRCodeDialog.Builder();
+ builder.title(getString(R.string.bind_driver_qr_title))
+ .cancelStr(getString(R.string.qr_cancel))
+ .qrBm(bmQr).build(getContext()).show();
+ }else {
+ CallerLogger.d(M_BUS + TAG,"bmQr = null ");
+ }
+ }
+ }
+
+ @Override
+ protected void onArriveStation() {
+ mPresenter.onAutopilotArriveAtStation(null);
+ mPresenter.arriveStation(null,"点击进站触发进站操作");
+ }
+
+ @Override
+ protected void debugArrivedStation() {
+ mPresenter.onAutopilotArriveAtStation(null);
+ mPresenter.arriveStation(null,"点击debug进站按钮触发进站操作");
+ }
+
+ @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;
+ }
+
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (stationList == null) {
+ // 获取小巴数据失败
+ return;
+ }
+
+ showStationsPanel();
+ showOrHideSwitchLineBtn(false);
+
+ mLineName.setText(lineName);
+ mTaskTime.setText(getString(R.string.bus_line_time_tag)+ lineTime);
+ // 渲染小巴路线数据
+ updateBusStationStatus(stationList,arrivingOrArrivedIndex,isArrived);
+ }
+ },UiThreadHandler.MODE.QUEUE);
+ }
+
+ 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(ResourcesUtils.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(ResourcesUtils.getString(R.string.bus_station_txt_tag_end));
+ }else {
+ thirdStationItem.setStationTag("");
+ }
+
+ //圆点: 0:灰色 过站 1:绿色 到站或者即将到站 2:蓝色:未到站
+ if (arrivingOrArrivedIndex == 0 && isArrived){
+ firstStationItem.setStationNameColor(ResourcesUtils.getColor(R.color.bus_line_station_color_selected));
+ secondStationItem.setStationNameColor(ResourcesUtils.getColor(R.color.bus_arrived_station_name_text_color));
+ thirdStationItem.setStationNameColor(ResourcesUtils.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(ResourcesUtils.getColor(R.color.bus_station_tag_txt_un_color));
+ secondStationItem.setStationNameColor(ResourcesUtils.getColor(R.color.bus_station_tag_txt_un_color));
+ thirdStationItem.setStationNameColor(ResourcesUtils.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(ResourcesUtils.getColor(R.color.bus_station_tag_txt_un_color));
+ secondStationItem.setStationNameColor(ResourcesUtils.getColor(R.color.bus_line_station_color_selected));
+ thirdStationItem.setStationNameColor(ResourcesUtils.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(ResourcesUtils.getString(R.string.bus_station_txt_tag_start));
+ thirdStationItem.setStationTag(ResourcesUtils.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(ResourcesUtils.getColor(R.color.bus_line_station_color_selected));
+ thirdStationItem.setStationNameColor(ResourcesUtils.getColor(R.color.bus_arrived_station_name_text_color));
+ firstStationItem.setStationPointBg(1);
+ firstStationItem.setStationArrowBg(2);
+ thirdStationItem.setStationPointBg(0);
+
+ }else {
+ firstStationItem.setStationNameColor(ResourcesUtils.getColor(R.color.bus_station_tag_txt_un_color));
+ thirdStationItem.setStationNameColor(ResourcesUtils.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(ResourcesUtils.getString(R.string.bus_switch_line_btn));
+ }else {//显示结束路线
+ mSwitchLine.setTag(1);
+ mSwitchLine.setText(ResourcesUtils.getString(R.string.bus_close_line_btn));
+ }
+ }
+
+ public void hideOchBus() {
+// tvNotice.setVisibility(View.GONE);
+ }
+
+ @Override
+ public int getStationPanelViewId() {
+ return R.layout.shuttle_fragment_och;
+ }
+
+ @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.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.d(SceneConstant.M_BUS, "clearBusStationsMarkers --------->");
+ smallMapView.clearPolyline();
+ }
+
+ /**
+ * 绘制地图起点终点
+ *
+ * @param isAdd
+ * @param uuid
+ */
+ private void setOrRemoveMapMaker(boolean isAdd, String uuid, double lat, double longi,int resourceId) {
+ if (isAdd) {
+ Runnable setMapMarkerRunnable = () -> {
+ CallerLogger.d(M_BUS + "setMapMaker= "+Thread.currentThread().getName(),
+ uuid + "=latitude=" + lat + ",longitude=" + longi);
+
+ Point.Options.Builder builder = new Point.Options.Builder(BusConst.TYPE_MARKER_BUS_ORDER, Level.MAP_MARKER)
+ .setId(uuid)
+ .anchor(0.5f, 0.5f)
+ .set3DMode(true)
+ .isUseGps(true)
+ .controlAngle(false)
+ .icon3DRes(resourceId)
+ .latitude(lat)
+ .longitude(longi);
+ IMoGoOverlayManager overlayManager = CallerMapUIServiceManager.INSTANCE.getOverlayManager();
+ if (overlayManager != null) {
+ overlayManager.showOrUpdatePoint(builder.build(),DEFAULT);
+ }
+ };
+
+ OCHThreadPoolManager.getsInstance().execute(setMapMarkerRunnable);
+
+ }else {
+ Runnable removeMapMarkerRunnable = () -> {
+ CallerLogger.d(M_BUS + "RemoveMapMaker="+Thread.currentThread().getName(),
+ uuid+"=latitude="+lat+",longitude="+longi);
+ Objects.requireNonNull(CallerMapUIServiceManager.INSTANCE.getOverlayManager()).removePoint(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.getState()
+ == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) {
+ ToastUtils.showLong(ResourcesUtils.getString(R.string.bus_switch_line_btn_warning1));
+ return;
+ }
+ if ((int)mSwitchLine.getTag() == 0){//切换路线
+ Intent intent = new Intent(getContext(), BusSwitchLineActivity.class);
+ ActivityUtils.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/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/model/BusLineModel.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/model/BusLineModel.java
new file mode 100644
index 0000000000..ef35581c24
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/model/BusLineModel.java
@@ -0,0 +1,148 @@
+package com.mogo.och.shuttle.model;
+
+import android.content.Context;
+
+import com.mogo.commons.AbsMogoApplication;
+import com.mogo.commons.storage.SharedPrefsMgr;
+import com.mogo.eagle.core.utilcode.util.NetworkUtils;
+import com.mogo.eagle.core.utilcode.util.ToastUtils;
+import com.mogo.och.shuttle.R;
+import com.mogo.och.shuttle.bean.BusQueryLineTaskResponse;
+import com.mogo.och.shuttle.bean.BusQueryLinesResponse;
+import com.mogo.och.shuttle.bean.BusRoutesResponse;
+import com.mogo.och.shuttle.callback.IBusLinesCallback;
+import com.mogo.och.shuttle.net.OrderServiceManager;
+import com.mogo.och.shuttle.ui.BusSwitchLineActivity;
+import com.mogo.och.common.module.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 线路ID
+ * @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) {
+ SharedPrefsMgr.getInstance().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/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/model/OrderModel.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/model/OrderModel.java
new file mode 100644
index 0000000000..c16e418b48
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/model/OrderModel.java
@@ -0,0 +1,1299 @@
+package com.mogo.och.shuttle.model;
+
+import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS;
+import static com.mogo.och.shuttle.constant.BusConst.DELAY_10S;
+import static com.mogo.och.shuttle.constant.BusConst.STATION_STATUS_ARRIVING;
+import static com.mogo.och.shuttle.constant.BusConst.STATION_STATUS_STOPPED;
+
+import android.content.Context;
+import android.text.TextUtils;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.elegant.network.utils.GsonUtil;
+import com.mogo.aicloud.services.socket.IMogoOnMessageListener;
+import com.mogo.eagle.core.function.api.telematic.IReceivedMsgListener;
+import com.mogo.eagle.core.function.call.telematic.CallerTelematicListenerManager;
+import com.mogo.eagle.core.utilcode.util.CoordinateUtils;
+import com.mogo.commons.AbsMogoApplication;
+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.eagle.core.utilcode.util.DateTimeUtils;
+import com.mogo.eagle.core.utilcode.util.StringUtils;
+import com.mogo.och.common.module.manager.autopilot.autopilot.OchAutoPilotManager;
+import com.mogo.och.common.module.manager.autopilot.location.OchLocationManager;
+import com.mogo.och.common.module.manager.autopilot.line.LineManager;
+import com.mogo.och.common.module.manager.distance.TrajectoryAndDistanceManager;
+import com.mogo.och.common.module.manager.socket.lan.LanSocketManager;
+import com.mogo.och.common.module.manager.socket.lan.bean.BusinessType;
+import com.mogo.och.common.module.voice.VoiceNotice;
+import com.mogo.och.shuttle.bean.BusRoutesResponse;
+import com.mogo.och.shuttle.util.ShuttleVoiceManager;
+import com.mogo.och.common.module.manager.socket.lan.bean.AppConnectMsg;
+import com.mogo.och.common.module.manager.socket.lan.bean.BaseDPMsg;
+import com.mogo.och.common.module.manager.socket.lan.bean.DPMsgType;
+import com.mogo.och.common.module.manager.socket.lan.bean.LoginCacheStatus;
+import com.mogo.och.common.module.manager.socket.lan.bean.TaskDetailsMsg;
+import com.mogo.och.common.module.biz.login.LoginStatusManager;
+import com.mogo.och.common.module.manager.autopilot.autopilot.ArrivedStation;
+import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager;
+import com.mogo.och.common.module.utils.MultiRequestLimitChecker;
+import com.mogo.och.common.module.utils.OCHThreadPoolManager;
+import com.mogo.och.data.bean.BusStationBean;
+import com.mogo.och.common.module.manager.socket.cloud.data.SystemMsg;
+import com.mogo.och.common.module.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.call.autopilot.CallerAutoPilotControlManager;
+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.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.shuttle.R;
+import com.mogo.och.data.bean.BusRoutesResult;
+import com.mogo.och.shuttle.callback.IBusADASStatusCallback;
+import com.mogo.och.shuttle.callback.IBusControllerStatusCallback;
+import com.mogo.och.shuttle.callback.IRefreshBusStationsCallback;
+import com.mogo.och.shuttle.callback.ISlidePannelHideCallback;
+import com.mogo.och.shuttle.constant.BusConst;
+import com.mogo.och.shuttle.net.OrderServiceManager;
+import com.mogo.och.shuttle.util.BusAnalyticsManager;
+import com.mogo.och.shuttle.util.BusSendTripInfoManager;
+import com.mogo.och.shuttle.util.BusTrajectoryManager;
+import com.mogo.och.common.module.manager.socket.cloud.OCHSocketMessageManager;
+import com.mogo.och.common.module.network.OchCommonServiceCallback;
+import com.mogo.och.common.module.callback.OchAdasStartFailureCallback;
+import com.mogo.och.common.module.manager.socket.cloud.AbnormalFactorsLoopManager;
+import com.mogo.och.common.module.manager.autopilot.OCHAdasAbilityManager;
+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.manager.socket.lan.bean.BusCacheKey;
+import com.mogo.och.data.bean.BusTransferData;
+import com.mogo.och.data.manager.cache.CacheDataManager;
+
+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;
+
+/**
+ * @author congtaowang
+ * @since 2021/3/23
+ *
+ * 小巴订单管理
+ */
+public class OrderModel {
+ private final String TAG = OrderModel.class.getSimpleName();
+ private int backgroundCurrentStationIndex = 0;//A->B 此处值是A站点索引
+ private static volatile OrderModel sInstance;
+ 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 IRefreshBusStationsCallback refreshBusStationsCallback;
+ private ISlidePannelHideCallback slidePanelHideCallback;
+ private IBusControllerStatusCallback mControllerStatusCallback; //Model->Presenter:VR mode等
+ private IBusADASStatusCallback mADASStatusCallback;
+
+ private volatile boolean isArrivedStation = false;
+
+ //0: 代表没有启动过 1代表是启动第一次,当>=1 代表是重试 每次到站/路线结束清空置为0
+ private volatile int firstStartAutopilot = 0;
+
+ 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();
+ // 定位监听
+ OchLocationManager.addGCJ02Listener(TAG,5,mMapLocationListener);
+
+ //开启自驾后 异常信息返回
+ OCHAdasAbilityManager.getInstance().setAdasStartFailureCallback(mAdasStartFailureListener);
+
+ OCHSocketMessageManager.INSTANCE.registerSocketMessageListener(//监听运营消息
+ OCHSocketMessageManager.msgMonitorType,
+ mMogoOnMessageListener);
+
+ TicketModel.INSTANCE.load();
+
+ AbnormalFactorsLoopManager.INSTANCE.startLoopAbnormalFactors(mContext);
+
+ //监听乘客屏发来的消息
+ CallerTelematicListenerManager.INSTANCE.addListener(TAG,mReceivedMsgListener);
+
+ //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.d(M_BUS + TAG, "UndeliverableException");
+ }
+ if ((e instanceof IOException)) {//
+ // fine, irrelevant network problem or API that throws on cancellation
+ CallerLogger.d(M_BUS + TAG, "IOException");
+ return;
+ }
+ if (e instanceof InterruptedException) {
+ // fine, some blocking code was interrupted by a dispose call
+ CallerLogger.d(M_BUS + TAG, "InterruptedException");
+ return;
+ }
+ if ((e instanceof NullPointerException) || (e instanceof IllegalArgumentException)) {
+ // that's likely a bug in the application
+ CallerLogger.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.d(M_BUS + TAG, "IllegalStateException");
+ Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
+ return;
+ }
+ CallerLogger.d(M_BUS + TAG, "Undeliverable exception");
+ }
+ });
+ }
+
+ private final IReceivedMsgListener mReceivedMsgListener =
+ new IReceivedMsgListener() {
+ @Override
+ public void onDemoMode(boolean isDemoMode) {
+
+ }
+
+ @Override
+ public void onReceivedServerSn(@Nullable String sn) {
+
+ }
+
+ @Override
+ public void onReceivedMsg(int type, @NonNull byte[] byteArray) {
+ if (OchCommonConst.BUSINESS_STRING == type){
+ CallerLogger.d(M_BUS + BaseDPMsg.TAG,new String(byteArray));
+ BaseDPMsg msg = GsonUtils.fromJson(new String(byteArray),BaseDPMsg.class);
+ if(msg!=null) {
+ if (msg.getType() == DPMsgType.TYPE_TASK_DETAILS.getType()) {
+ sendTaskDetailsToClients();
+ }
+ }
+ }
+ }
+ };
+
+ private final IMogoOnMessageListener mMogoOnMessageListener =
+ new IMogoOnMessageListener() {
+ @Override
+ public Class target() {
+ return SystemMsg.class;
+ }
+
+ @Override
+ public void onMsgReceived(SystemMsg obj) {
+ if (obj == null){
+ CallerLogger.d(M_BUS + TAG, "onMsgReceived = null");
+ return;
+ }
+ CallerLogger.i(M_BUS + TAG,"onMsgReceived = "+obj.getContext());
+ List list = obj.getScreenList();
+ CallerLogger.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(),-1);
+ LanSocketManager.sendMsgToClient(msg);
+ }
+
+ }
+ };
+
+ public void setAdasStatusCallback(IBusADASStatusCallback callback){
+ this.mADASStatusCallback = callback;
+ }
+
+ public void setRefreshBusStationsCallback(IRefreshBusStationsCallback callback){
+ this.refreshBusStationsCallback = callback;
+ }
+
+ public void setSlidePanelHideCallback(ISlidePannelHideCallback callback) {
+ this.slidePanelHideCallback = callback;
+ }
+
+ public void setControllerStatusCallback(IBusControllerStatusCallback callback) {
+ this.mControllerStatusCallback = callback;
+ }
+
+ public void release() {
+
+ // 注销定位监听
+ OchLocationManager.removeGCJ02Listener(TAG);
+
+ OCHAdasAbilityManager.getInstance().setAdasStartFailureCallback(null);
+
+ OCHSocketMessageManager.INSTANCE.releaseSocketMessageListener(
+ OCHSocketMessageManager.msgMonitorType);
+ OCHSocketMessageManager.INSTANCE.releaseSocketMessageListener(
+ OCHSocketMessageManager.msgWriteOffPassengerType);
+
+ AbnormalFactorsLoopManager.INSTANCE.stopLoopAbnormalFactors();
+ //监听乘客屏发来的消息
+ CallerTelematicListenerManager.INSTANCE.removeListener(TAG);
+ }
+
+ private Object readResolve() {
+ // 阻止反序列化,必须实现 Serializable 接口
+ return sInstance;
+ }
+
+ private final OchAdasStartFailureCallback mAdasStartFailureListener = new OchAdasStartFailureCallback() {
+ @Override
+ public void brakeStatusChanged(boolean isBrakeAvailable) {
+
+ }
+
+ @Override
+ public void onStartAutopilotFailure(@NotNull String startFailedCode, @NonNull String startFailedMessage) {
+ BusAnalyticsManager.getInstance().triggerStartAutopilotFailureEventByAdas(startFailedCode, startFailedMessage,System.currentTimeMillis());
+ if (mADASStatusCallback != null && !FunctionBuildConfig.isDemoMode){
+ CallerLogger.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;
+ if (mControllerStatusCallback != null) {
+ mControllerStatusCallback.onCarLocationChanged(mogoLocation);
+ }
+
+ //是否到站的围栏判断 离站状态并且自动驾驶还未触发到站
+ if (isGoingToNextStation && !isArrivedStation) {
+ OCHThreadPoolManager.getsInstance().locationExecute(new Runnable() {
+ @Override
+ public void run() {
+ judgeArrivedStation(mogoLocation);
+ }
+ });
+ }
+ }
+ };
+
+ //根据围栏判断,是否到达站点
+ private void judgeArrivedStation(MogoLocation location) {
+
+ if (backgroundCurrentStationIndex + 1 > stationList.size() - 1) {
+ CallerLogger.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.d(M_BUS + TAG, "行程日志-judgeArrivedStation() distance = " + distance
+ + " to " + upcomingStation.getName());
+ onArriveAt(null,"兜底:根据定位计算到站");
+ }
+ }
+
+ public void queryBusCacheRoutes(){
+
+ String loginStr = CacheDataManager.Companion.getInstance().getCacheData(
+ mContext, BusCacheKey.BUS_LOGIN_STATUS_CACHE);
+ if (!loginStr.isEmpty()){
+ LoginCacheStatus status = GsonUtils.fromJson(loginStr,LoginCacheStatus.class);
+ LoginStatusManager.setLoginStatus(status.getLoginStatus());
+ if (status.getUpdateTime() > DateTimeUtil.getTodayStartTime() &&
+ status.getLoginStatus() == 1){//登陆
+
+ String cacheData = CacheDataManager.Companion.getInstance().getCacheData(mContext,
+ BusCacheKey.BUS_LINE_CACHE);
+
+ if (cacheData == null || cacheData.isEmpty()){
+ queryBusRoutes();
+ }else {
+ BusTransferData data = GsonUtils.fromJson(cacheData,BusTransferData.class);
+ getCacheRouteSuccess(data.getRoutesResult());
+ }
+ }else{ // 未登陆
+ CacheDataManager.Companion.getInstance().clearCacheData(mContext,BusCacheKey.BUS_LOGIN_STATUS_CACHE);
+ sendTaskDetailsToClients();
+ }
+ }
+ }
+
+ private void getCacheRouteSuccess(BusRoutesResult data){
+ if (data == null || data.getSites() == null
+ || data.getSites().isEmpty()
+ || data.getWriteVersion() < DateTimeUtil.getTodayStartTime()) {
+ //当为空时,显示无绑定路线图
+ queryBusRoutes();
+ CacheDataManager.Companion.getInstance().clearCacheData(mContext, BusCacheKey.BUS_LINE_CACHE);
+ return;
+ }
+ CallerLogger.d(M_BUS + TAG, "获取到小巴路线数据: " + GsonUtils.toJson(data));
+ updateBusStatus(data);
+ }
+
+ /**
+ * 查询小巴路线
+ */
+ public void queryBusRoutes() {
+ CallerLogger.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.d(M_BUS + TAG, "获取到小巴路线数据:空 ");
+ if (refreshBusStationsCallback != null) {
+ refreshBusStationsCallback.updateEmptyUi();
+ }
+ updateBusStatus(null);
+ clearAutopilotControlParameters();
+ closeBeautificationMode();
+ clearStartAutopilotTag();
+ removeTipRunnables();
+ CacheDataManager.Companion.getInstance().clearCacheData(mContext,BusCacheKey.BUS_LINE_CACHE);
+ return;
+ }
+
+ if (busRoutesResult == null || busRoutesResult.getWriteVersion() < data.getResult().getWriteVersion()){
+ CallerLogger.d(M_BUS + TAG, "更新小巴路线数据: " + data);
+ updateBusStatus(data.getResult());
+ pushCacheTransferData(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.d(M_BUS + TAG, "结束当前路线abortTask");
+ if(busRoutesResult==null){
+ ToastUtils.showLong("数据异常、请稍后再试");
+ return;
+ }
+ OrderServiceManager.abortTask(mContext, busRoutesResult.getTaskId()
+ , new OchCommonServiceCallback() {
+ @Override
+ public void onSuccess(BaseData o) {
+ CallerLogger.d(M_BUS + TAG, "abortTask success: " + o);
+ if (o.code == 0) { // 重置成功
+ endOrAbortTaskSuccess();
+ clearBusStationDatas();
+ queryBusRoutes();
+ removeTipRunnables();
+ // 取消自驾
+ CallerAutoPilotControlManager.INSTANCE.cancelAutoPilot();
+ setTrajectoryStation(null,null,-1L);
+ }
+ }
+
+ @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);
+ }
+
+ CacheDataManager.Companion.getInstance().clearCacheData(mContext, BusCacheKey.BUS_LINE_CACHE);
+ busRoutesResult = null;
+
+ sendTaskDetailsToClients();
+ }
+
+ /**
+ * 离站上报成功后渲染站点
+ * 服务端返回的OchBusRoutesResult逻辑, 离开站为当前站, 到达下一站后才会将下一站置为当前站,
+ * 车机端展示是离开当前站,下一站设置为当前站, 所以服务端数据回来要做处理,不能直接渲染
+ */
+ private void leaveStationSuccess(int leaveIndex, String leaveStation,
+ String nextStation,String nextStationKr,
+ long writeVersion) {
+
+ onStartAutopilot(leaveIndex);
+
+ leaveTTSTips(nextStation,nextStationKr);
+
+ 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);
+ }
+
+ reBuildCacheRouteData(leaveIndex,BusConst.STATION_STATUS_STOPPED,true,writeVersion);
+ }
+
+ private void reBuildCacheRouteData(int currentIndex, int currentDrivingStatus, boolean isLeaving
+ , long writeVersion) {
+ if (busRoutesResult != null){
+ busRoutesResult.setWriteVersion(writeVersion);
+ List sites = busRoutesResult.getSites();
+ BusStationBean bean = sites.get(currentIndex);
+ bean.setDrivingStatus(currentDrivingStatus);
+ bean.setLeaving(isLeaving);
+ sites.set(currentIndex,bean);
+ if (currentDrivingStatus == STATION_STATUS_STOPPED && !isLeaving){
+ BusStationBean beanPre = sites.get(currentIndex -1);
+ beanPre.setDrivingStatus(BusConst.STATION_STATUS_LEAVING);
+ beanPre.setLeaving(false);
+ sites.set(currentIndex -1,beanPre);
+ }
+ //busRoutesResult.setSite(sites);
+
+ pushCacheTransferData(busRoutesResult);
+
+ updateBusStatus(busRoutesResult);
+ }
+ }
+
+ private void onStartAutopilot(int leaveIndex) {
+ //开启自动驾驶 2.10.0: 如果自动驾驶状态下开启, 非自动驾驶状态下不开启,需手动点击自动驾驶按钮开启
+ isGoingToNextStation = true;
+ if (CallerAutoPilotStatusListenerManager.INSTANCE.getState()
+ == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) {
+ startAutopilot(false, leaveIndex);
+ } else {
+ firstStartAutopilot = 0;
+ }
+ }
+
+ /**
+ * 开启自动驾驶
+ *
+ * @param isRestart
+ */
+ private void startAutopilot(boolean isRestart, int leaveIndex) {
+ BusAnalyticsManager.getInstance().triggerClickStartAutopilotTime(System.currentTimeMillis());
+
+ //1、判断轨迹url是否可用
+ if(busRoutesResult!=null){
+ //根据开关和后台是否发布轨迹启动自驾
+ if (FunctionBuildConfig.isPassStartAutopilotCommand
+ && TextUtils.isEmpty(busRoutesResult.csvFileUrl)
+ && TextUtils.isEmpty(busRoutesResult.csvFileUrlDPQP)
+ ) {
+ ToastUtils.showLong("无发布轨迹, 请发布后重试");
+ CallerLogger.e(
+ TAG, "isPassStartAutopilotCommand = " +
+ FunctionBuildConfig.isPassStartAutopilotCommand
+ + "busRoutesResult.csvFileUrl = " + busRoutesResult.csvFileUrl
+ );
+ return;
+ }
+ }
+ //2、6个条件判断
+ if (!CallerAutoPilotControlManager.INSTANCE.isCanStartAutopilot(true,0)) {
+ return;
+ }
+ // 3、距离轨迹15m计算
+ //3、距离轨迹15m计算
+ String resion = OchAutoPilotManager.canStartAutoPilot(busRoutesResult.getLineId());
+ if(TrajectoryAndDistanceManager.errorTypeNoneLineId.equals(resion)){
+ MogoLocation nextStationPoint = new MogoLocation();
+ if (backgroundCurrentStationIndex < stationList.size() - 1) {
+ BusStationBean nextStation = stationList.get(backgroundCurrentStationIndex + 1);
+ nextStationPoint.setLongitude(nextStation.getGcjLon());
+ nextStationPoint.setLatitude(nextStation.getGcjLat());
+ }
+ BusStationBean busStationBean = stationList.get(backgroundCurrentStationIndex);
+ MogoLocation currentStationPoint = new MogoLocation();
+ currentStationPoint.setLongitude(busStationBean.getGcjLon());
+ currentStationPoint.setLatitude(busStationBean.getGcjLat());
+ setTrajectoryStation(currentStationPoint,nextStationPoint, (long) busRoutesResult.getLineId());
+ resion = OchAutoPilotManager.canStartAutoPilot(busRoutesResult.getLineId());
+ }
+ if(!StringUtils.isEmpty(resion)){
+ ToastUtils.showShort(resion);
+ VoiceNotice.showNotice(resion);
+ return;
+ }
+ //4、ssm 给出数据
+ if (!OchAutoPilotManager.canStartAutoPilotSSM()) {
+ triggerUnableStartAPReasonEvent();
+ return;
+ }
+
+ firstStartAutopilot++;
+
+ triggerStartServiceEvent(isRestart, false);
+
+ AutopilotControlParameters parameters = initAutopilotControlParameters(leaveIndex);
+ if (null == parameters) {
+ CallerLogger.e(M_BUS + TAG, "行程日志-AutopilotControlParameters is empty.");
+ return;
+ }
+
+ OchAutoPilotManager.startAutoPilot(parameters);
+
+ CallerLogger.d(M_BUS + TAG, "行程日志-开启自动驾驶====" + GsonUtil.jsonFromObject(parameters)
+ + " startLatLon=" + parameters.startName + ",endLatLon=" + parameters.endName +
+ "isRestart = " + isRestart);
+
+ if (mControllerStatusCallback != null) {
+ mControllerStatusCallback.startOpenAutopilot();
+ }
+ }
+
+ /**
+ * 到站后重置站点状态
+ */
+ private void arriveSiteStation(String changeInfo) {
+ OchChainLogManager.writeChainLog("触发进站", changeInfo);
+ if ( backgroundCurrentStationIndex +1 > stationList.size() - 1 ) { //到站短时间内调用多次
+ CallerLogger.e( M_BUS + TAG, "数组越界" );
+ return;
+ }
+ int arrivedStationIndex = backgroundCurrentStationIndex + 1;
+ String arriveStation = stationList.get(arrivedStationIndex).getName();
+ String arriveStationKr = stationList.get(arrivedStationIndex).getNameKr();
+ String departureStopName = stationList.get(backgroundCurrentStationIndex).getName();
+ CallerLogger.d(M_BUS + TAG, "arriveSiteStation-currentStationIndex = " + arrivedStationIndex);
+
+ isArrivedStation = true;
+ isGoingToNextStation = false;
+
+ long writeVersion = DateTimeUtil.getCurrentTimeStamp();
+ arriveStationSuccess(arrivedStationIndex, departureStopName,
+ arriveStation,arriveStationKr,writeVersion);
+
+ String requestId = MultiRequestLimitChecker.Companion.generateRequestId(TAG + "-arriveSiteStation"
+ , String.valueOf(stationList.get(arrivedStationIndex).getSiteId())
+ , String.valueOf(busRoutesResult.getTaskId()));
+ if (!MultiRequestLimitChecker.Companion.getInstance().canMakeRequest(requestId, 5)) {
+ CallerLogger.d(M_BUS + TAG, "arriveSiteStation-MultiRequestLimitChecker: 超过最大请求数,本次请求return");
+ return;
+ }
+ OrderServiceManager.arriveSiteStation(mContext,
+ stationList.get(arrivedStationIndex).getSeq(),
+ stationList.get(arrivedStationIndex).getSiteId(),
+ busRoutesResult.getTaskId(),writeVersion,
+ new OchCommonServiceCallback() {
+ @Override
+ public void onSuccess(BaseData o) {
+ CallerLogger.d(M_BUS + TAG, "行程日志-arriveSiteStation success");
+ MultiRequestLimitChecker.Companion.getInstance().decreaseRequestCount(requestId);
+ }
+
+ @Override
+ public void onError() {
+ MultiRequestLimitChecker.Companion.getInstance().decreaseRequestCount(requestId);
+ }
+
+ @Override
+ public void onFail(int code, String failMsg) {
+ MultiRequestLimitChecker.Companion.getInstance().decreaseRequestCount(requestId);
+ }
+ });
+ }
+
+ private void arriveStationSuccess(int arrivedStationIndex, String departureStopName,
+ String arriveStation,String arriveStationKr,
+ long writeVersion) {
+ 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);
+ }
+
+ ShuttleVoiceManager.INSTANCE.arrivedStationBus(arriveStation,arriveStationKr);
+
+ sendArrivedStationToClient(arriveStation);
+
+ reBuildCacheRouteData(arrivedStationIndex, BusConst.STATION_STATUS_STOPPED,false,writeVersion);
+ }
+
+ private void sendTaskDetailsToClients() {
+
+ BusTransferData data = new BusTransferData(LoginStatusManager.isLogin() ? 1:0,busRoutesResult);
+ TaskDetailsMsg msg = new TaskDetailsMsg(GsonUtils.toJson(data), BusinessType.shuttle);
+ CallerLogger.d(M_BUS + TAG, "sendTaskDetailsToClients = " + GsonUtils.toJson(msg));
+ LanSocketManager.sendMsgToClient(msg);
+ }
+
+ private void pushCacheTransferData(BusRoutesResult result) {
+ BusTransferData data = new BusTransferData(LoginStatusManager.isLogin() ? 1:0,result);
+ CallerLogger.d(M_BUS + TAG, "pushCacheTransferData = " + GsonUtils.toJson(data));
+ CacheDataManager.Companion.getInstance().putCacheData(mContext,
+ BusCacheKey.BUS_LINE_CACHE,
+ GsonUtils.toJson(data));
+ }
+
+ private void sendArrivedStationToClient(String arriveStation) {
+ AppConnectMsg arrivedMsg = new AppConnectMsg(false,true,String.format(mContext
+ .getString(R.string.bus_arrived_station_tip),
+ arriveStation),-1);
+ LanSocketManager.sendMsgToClient(arrivedMsg);
+ }
+
+ private void sendStartStationToClient(String nextStation) {
+ AppConnectMsg startMsg = new AppConnectMsg(false,true,String.format(mContext
+ .getString(R.string.bus_leave_station_tip),
+ nextStation),-1);
+
+ UiThreadHandler.postDelayed(()-> LanSocketManager.sendMsgToClient(startMsg),DELAY_10S);
+ }
+
+ private void sendEndTaskToClient() {
+ AppConnectMsg endMsg = new AppConnectMsg(false,true,mContext
+ .getString(R.string.bus_end_task_tip),-1);
+ LanSocketManager.sendMsgToClient(endMsg);
+ }
+
+ public void sendWriteOffNumToClient(String msg){
+ AppConnectMsg passengerMsg = new AppConnectMsg(false,true,msg,-1);
+ LanSocketManager.sendMsgToClient(passengerMsg);
+ }
+
+ /**
+ * 离站上报
+ */
+ public void leaveStation() {
+ CallerLogger.d(M_BUS + TAG, "leaveStation-backgroundCurrentStationIndex = " + backgroundCurrentStationIndex);
+ if(busRoutesResult==null){
+ ToastUtils.showLong("数据异常、请稍后再试");
+ return;
+ }
+ String nextStationName = "";
+ String nextStationNameKr = "";
+ MogoLocation nextStationPoint = new MogoLocation();
+ if (backgroundCurrentStationIndex < stationList.size() - 1) {
+ BusStationBean nextStation = stationList.get(backgroundCurrentStationIndex + 1);
+ nextStationName = nextStation.getName();
+ nextStationNameKr = nextStation.getNameKr();
+ nextStationPoint.setLongitude(nextStation.getGcjLon());
+ nextStationPoint.setLatitude(nextStation.getGcjLat());
+ }
+ final String currentStationName = stationList.get(backgroundCurrentStationIndex).getName();
+ String finalNextStationName = nextStationName;
+ String finalNextStationNameKr = nextStationNameKr;
+
+ isArrivedStation = false;
+ CallerLogger.d(M_BUS + TAG, "行程日志-离站成功开往下一站====");
+
+ long writeVersion = DateTimeUtil.getCurrentTimeStamp();
+ leaveStationSuccess(backgroundCurrentStationIndex, currentStationName,
+ finalNextStationName,finalNextStationNameKr,writeVersion);
+
+ BusStationBean busStationBean = stationList.get(backgroundCurrentStationIndex);
+ MogoLocation currentStationPoint = new MogoLocation();
+ currentStationPoint.setLongitude(busStationBean.getGcjLon());
+ currentStationPoint.setLatitude(busStationBean.getGcjLat());
+ setTrajectoryStation(currentStationPoint,nextStationPoint, (long) busRoutesResult.getLineId());
+
+ String changeInfo = "taskId:" + busRoutesResult.getTaskId() + "--lineId:" + busRoutesResult.getLineId() +
+ "--currentStationName:"+currentStationName+"--finalNextStationName:"+finalNextStationName;
+ OchChainLogManager.writeChainLog("滑动出发", changeInfo);
+ OrderServiceManager.leaveStation(mContext,
+ stationList.get(backgroundCurrentStationIndex).getSeq(),
+ stationList.get(backgroundCurrentStationIndex).getSiteId(),
+ busRoutesResult.getTaskId(),writeVersion,
+ new OchCommonServiceCallback() {
+ @Override
+ public void onSuccess(BaseData o) {
+ OchChainLogManager.writeChainLog("滑动出发成功", changeInfo);
+ }
+
+
+ @Override
+ public void onError() {
+ }
+
+ @Override
+ public void onFail(int code, String failMsg) {
+ }
+ });
+ }
+
+ //车站10s后播报
+ private void leaveTTSTips(String nextStation,String nextStationKr) {
+ UiThreadHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {//延迟10s播报
+ ShuttleVoiceManager.INSTANCE.leaveStationBus(nextStation,nextStationKr);
+ }
+ },DELAY_10S);
+
+ }
+
+ /**
+ * 关闭美化模式
+ */
+ public void closeBeautificationMode() {
+ if (FunctionBuildConfig.isDemoMode) {//收车结束美化
+ FunctionBuildConfig.isIgnoreConditionsDrawAutopilotTrajectoryData = false; //是否强制绘制引导线
+ CallerAutoPilotControlManager.INSTANCE.setIgnoreConditionDraw(false);// 同步给乘客屏
+ CallerAutoPilotControlManager.INSTANCE.setIPCDemoMode(false);//是否自动启动自驾
+ CallerLogger.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) {
+ LineManager.setLineId(-1);
+ return;
+ }
+ busRoutesResult = result;
+ LineManager.setLineId(busRoutesResult.getLineId());
+ stationList.clear();
+ stationList.addAll(result.getSites());
+ for (int i = 0; i < stationList.size(); i++) {
+ BusStationBean s = stationList.get(i);
+
+ CallerLogger.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();
+ }
+ }else {
+ removeTipRunnables();
+ }
+
+ BusStationBean currentStation = stationList.get(backgroundCurrentStationIndex);
+
+ CallerLogger.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.d(M_BUS + TAG, "美化模式-ignore:置为true(每次滑动出发)");
+ } else if (backgroundCurrentStationIndex > 0 && backgroundCurrentStationIndex < stationList.size() - 1) {
+ //美化模式下 中间站点到站 引导线要一直绘制,所以此处不出强制绘制不传false
+ CallerAutoPilotControlManager.INSTANCE.setIPCDemoMode(false);
+ CallerLogger.d(M_BUS + TAG, "美化模式-ignore:false(到达中间站)");
+ clearStartAutopilotTag();
+ } else {
+ closeBeautificationMode();
+ clearStartAutopilotTag();
+ }
+ }
+
+
+ if (currentStation.isLeaving() && slidePanelHideCallback != null) {
+ slidePanelHideCallback.hideSlidePanel();
+ }
+
+ sendTaskDetailsToClients();
+
+ //更新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);
+ ShuttleVoiceManager.INSTANCE.showLeafTime(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();
+ }
+ }
+
+ /**
+ * 在踩刹车、控制方向盘等操作后,会停止自动驾驶,重启自动驾驶的话相当于重新设置自动驾驶目的地
+ */
+ public void restartAutopilot() {
+ CallerLogger.d(M_BUS + TAG, "行程日志-重启自动驾驶===" + isGoingToNextStation);
+ //只去启动自动驾驶,不再去上报离站
+ startAutopilot(firstStartAutopilot >= 1, -1);
+ }
+
+ public boolean isRestartAutopilot() {
+ return firstStartAutopilot > 1;
+ }
+
+ /**
+ * 行程结束
+ */
+ private void travelOver() {
+
+ if (backgroundCurrentStationIndex >= stationList.size()) {
+ CallerLogger.e(M_BUS + TAG, "travel over index out of station list");
+ return;
+ }
+ CallerLogger.d(M_BUS + TAG, "单程结束====");
+ CallerAutoPilotControlManager.INSTANCE.cancelAutoPilot();
+ setTrajectoryStation(null,null,-1L);
+ endTask();
+ }
+
+ /**
+ * task正常结束
+ */
+ private void endTask() {
+ CallerLogger.d(M_BUS + TAG, "任务正常走完endTask()");
+ OrderServiceManager.endTask(mContext, busRoutesResult.getTaskId()
+ , new OchCommonServiceCallback() {
+ @Override
+ public void onSuccess(BaseData o) {
+ CallerLogger.d(M_BUS + TAG, "endTask success: " + o);
+ if (o.code == 0) {
+ endOrAbortTaskSuccess();
+ clearBusStationDatas();
+ queryBusRoutes();// 重新获取任务
+ removeTipRunnables();
+ ShuttleVoiceManager.INSTANCE.endOrderBus();
+ 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(ArrivedStation data,String type) {
+ if (backgroundCurrentStationIndex + 1 > stationList.size() - 1) {
+ CallerLogger.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.e(M_BUS + TAG, "行程日志-到站拦截,到站坐标不一致");
+ return;
+ }
+ }
+
+ if (isArrivedStation) return;
+
+ CallerLogger.d(M_BUS + TAG, "行程日志-当前==backgroundCurrentStationIndex="
+ + backgroundCurrentStationIndex);
+
+ arriveSiteStation(type);
+ }
+
+ public boolean isGoingToNextStation() {
+ return isGoingToNextStation;
+ }
+
+ // 登出
+ public void logout() {
+ LoginStatusManager.loginOut();
+ }
+
+ 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(), busRoutesResult.getLineId(),"",System.currentTimeMillis());
+ }
+
+ 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(), String.valueOf(busRoutesResult.getLineId()),"",
+ OCHAdasAbilityManager.getInstance().getAutopilotUnAbilityReason());
+ }
+
+ public BusRoutesResult getBusRoutesResult() {
+ return busRoutesResult;
+ }
+
+ public BusStationBean getBusNextStation() {
+ // A->B 的过程中A站点的信息
+ if (stationList == null || backgroundCurrentStationIndex >= stationList.size() - 1) {
+ return null;
+ }
+ return stationList.get(backgroundCurrentStationIndex);
+ }
+
+ public int getCurrentStationIndex() {
+ return backgroundCurrentStationIndex;
+ }
+
+ /**
+ * 将业务订单信息保存,鹰眼可取用
+ */
+ private void updateAutopilotControlParameters() {
+
+ AutopilotControlParameters parameters = initAutopilotControlParameters(-1);
+ if (null == parameters) {
+ CallerLogger.e(M_BUS + TAG, "AutopilotControlParameters is empty.");
+ return;
+ }
+ CallerLogger.d(M_BUS + TAG, "AutopilotControlParameters is update.");
+ CallerAutoPilotStatusListenerManager.INSTANCE.updateAutopilotControlParameters(parameters);
+ }
+
+ private void clearAutopilotControlParameters() {
+ CallerLogger.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.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.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.getName(),
+ 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 setTrajectoryStation(MogoLocation startStation,MogoLocation endStation,Long lineId){
+ TrajectoryAndDistanceManager.INSTANCE.setStationPoint(startStation,endStation,lineId);
+ }
+
+}
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/model/TicketModel.kt b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/model/TicketModel.kt
new file mode 100644
index 0000000000..53194a5363
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/model/TicketModel.kt
@@ -0,0 +1,218 @@
+package com.mogo.och.shuttle.model
+
+import com.elegant.network.utils.GsonUtil
+import com.mogo.aicloud.services.socket.IMogoOnMessageListener
+import com.mogo.commons.AbsMogoApplication
+import com.mogo.eagle.core.data.enums.EventTypeEnumNew
+import com.mogo.eagle.core.data.msgbox.MsgBoxBean
+import com.mogo.eagle.core.data.msgbox.MsgBoxType
+import com.mogo.eagle.core.data.msgbox.V2XMsg
+import com.mogo.eagle.core.function.api.telematic.IReceivedMsgListener
+import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxManager.saveMsgBox
+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.CallerLogger.i
+import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
+import com.mogo.eagle.core.utilcode.util.GsonUtils
+import com.mogo.och.shuttle.bean.WriteOffCountResponse
+import com.mogo.och.shuttle.bean.WriteOffPassenger
+import com.mogo.och.shuttle.net.OrderServiceManager
+import com.mogo.och.shuttle.util.ShuttleVoiceManager
+import com.mogo.och.common.module.manager.socket.lan.bean.BaseDPMsg
+import com.mogo.och.common.module.manager.socket.lan.bean.DPMsgType
+import com.mogo.och.common.module.manager.socket.lan.bean.WriteOffDevicesMsg
+import com.mogo.och.common.module.manager.socket.lan.bean.WriteOffMsg
+import com.mogo.och.common.module.manager.socket.cloud.OCHSocketMessageManager
+import com.mogo.och.common.module.constant.OchCommonConst
+import com.mogo.och.common.module.network.OchCommonServiceCallback
+import com.mogo.och.common.module.manager.loop.BizLoopManager
+import com.mogo.och.common.module.manager.loop.LoopInfo
+import io.reactivex.Observable
+import io.reactivex.ObservableEmitter
+import io.reactivex.ObservableOnSubscribe
+import io.reactivex.schedulers.Schedulers
+
+object TicketModel : IReceivedMsgListener, IMogoOnMessageListener {
+
+ private val TAG = "TicketModel"
+
+ private val SELECTWRITEOFFCOUNT = "SELECTWRITEOFFCOUNT"
+
+ private var emitterMain: ObservableEmitter?=null
+
+ private val observable = Observable.create(ObservableOnSubscribe { emitter -> emitterMain = emitter })
+
+ init {
+
+ //监听乘客屏发来的消息
+ CallerTelematicListenerManager.addListener(TAG, this)
+ OCHSocketMessageManager.registerSocketMessageListener( //监听核销乘客
+ OCHSocketMessageManager.msgWriteOffPassengerType,
+ this
+ )
+ }
+
+ fun load(){
+ BizLoopManager.setLoopFunction(
+ SELECTWRITEOFFCOUNT, LoopInfo(3,
+ TicketModel::selectWriteOffCount,scheduler = Schedulers.io()))
+ }
+
+ // 收到局域网的核验信息
+ override fun onReceivedMsg(type: Int, byteArray: ByteArray) {
+ if (OchCommonConst.BUSINESS_STRING == type) {
+ d(SceneConstant.M_BUS + TAG, "局域网核验"+String(byteArray))
+ val msg = GsonUtils.fromJson(String(byteArray), BaseDPMsg::class.java)
+ if (msg != null) {
+ if (msg.type == DPMsgType.TYPE_WRITEOFF_INFO.type) {
+ val writeOffMsg = GsonUtils.fromJson(String(byteArray), WriteOffMsg::class.java)
+ receiveWrteOffInfo(writeOffMsg)
+ } else if (msg.type == DPMsgType.TYPE_WRITEOFF_DEVICES_INFO.type) {
+ val writeOffMsg = GsonUtils.fromJson(String(byteArray), WriteOffDevicesMsg::class.java)
+ receiveWrteOffDevicesInfo(writeOffMsg)
+ }
+ }
+ }
+ }
+
+ override fun target(): Class {
+ return WriteOffPassenger::class.java
+ }
+
+ // 收到服务器的核验信息
+ override fun onMsgReceived(passenger: WriteOffPassenger?) {
+ //进行播报
+ i(SceneConstant.M_BUS + TAG, "后台socket 核验:passenger = " + GsonUtil.jsonFromObject(passenger))
+ if(passenger==null||passenger.passengerSize==0){
+ return
+ }
+ playPassenger(
+ passenger.passengerSize,
+ passenger.phone ?: "",
+ passenger.ticketName?:"",
+ passenger.orderNo?:""
+ )
+ selectWriteOffCount()
+ }
+
+ private fun selectWriteOffCount(){
+ val busRoutesResult = OrderModel.getInstance().busRoutesResult
+ val busNextStation = OrderModel.getInstance().busNextStation
+ if(busRoutesResult==null||busNextStation==null){
+ emitterMain?.onNext(0)
+ d(SceneConstant.M_BUS + TAG, "线路或者站点未空:${busRoutesResult}----${busNextStation}")
+ return
+ }
+ OrderServiceManager.queryBusTaskByLineId(AbsMogoApplication.getApp(),
+ "${busRoutesResult.taskId}",
+ "${busNextStation.siteId}",
+ object : OchCommonServiceCallback {
+ override fun onSuccess(data: WriteOffCountResponse?) {
+ data?.data?.let {
+ emitterMain?.onNext(it)
+ d(SceneConstant.M_BUS + TAG, "${busNextStation.name}核销人数:${it}")
+ }
+ }
+
+ override fun onFail(code: Int, msg: String?) {
+
+ }
+ })
+ }
+
+ fun getWriteOffCountObservable():Observable{
+ return observable
+ }
+
+ private fun receiveWrteOffInfo(writeOffMsg: WriteOffMsg?) {
+ if(writeOffMsg!=null) {
+ if (writeOffMsg.isScuccess != null) {
+ if (writeOffMsg.isScuccess == true) { // 核验成功
+ if(writeOffMsg.ticketSize==null||writeOffMsg.ticketSize==0){
+ return
+ }
+// playPassenger(
+// writeOffMsg.ticketSize?:0,
+// writeOffMsg.phone ?: "",
+// writeOffMsg.ticketName ?: "",
+// writeOffMsg.orderNo?:""
+// )
+ } else { // 核验失败
+ ShuttleVoiceManager.writeOffFaile("验票失败,${writeOffMsg.failedReason ?: ""}")
+ saveMsgBox(
+ MsgBoxBean(
+ MsgBoxType.V2X, V2XMsg(
+ EventTypeEnumNew.TYPE_ABNORMAL_VERIFICATION.poiType,
+ writeOffMsg.failedReason ?: "",
+ EventTypeEnumNew.TYPE_ABNORMAL_VERIFICATION.tts,
+ ""
+ )
+ )
+ )
+ }
+ }
+ }
+ }
+
+ private fun receiveWrteOffDevicesInfo(writeOffMsg: WriteOffDevicesMsg) {
+ if (writeOffMsg.isConnectScanner != null) {
+ val reason = if (writeOffMsg.reason == null) "" else writeOffMsg.reason!!
+ if (writeOffMsg.isConnectScanner==true) { // 链接成功
+ saveMsgBox(
+ MsgBoxBean(
+ MsgBoxType.V2X,
+ V2XMsg(
+ EventTypeEnumNew.TYPE_DEVICE_STATUS_NORMAL.poiType,
+ reason,
+ EventTypeEnumNew.TYPE_DEVICE_STATUS_NORMAL.tts,
+ ""
+ )
+ )
+ )
+ } else { // 核验失败
+ saveMsgBox(
+ MsgBoxBean(
+ MsgBoxType.V2X,
+ V2XMsg(
+ EventTypeEnumNew.TYPE_DEVICE_STATUS_ABNORMAL.poiType,
+ reason,
+ EventTypeEnumNew.TYPE_DEVICE_STATUS_ABNORMAL.tts,
+ ""
+ )
+ )
+ )
+ }
+ }
+ }
+
+ private fun playPassenger(ticketSize: Int,phone:String,ticketName:String,orderNo:String) {
+
+ if (ticketSize > 1) { //多人播报 "x人" ---》x人核验通过
+ OrderModel.getInstance().sendWriteOffNumToClient(ticketSize.toString() + "人核验通过")
+ } else { //是 1 播放 "滴" 2022.11.09 改为: "核验通过"
+ OrderModel.getInstance().sendWriteOffNumToClient("核验通过")
+ }
+ ShuttleVoiceManager.writeOffCount(ticketSize)
+
+ var tempPhone = phone
+ if (tempPhone.length > 8) {
+ //截取电话号码前三位
+ val phoneNumPre = tempPhone.substring(0, 3)
+ //截取电话号码后四位
+ val phoneNumFix = tempPhone.substring(7)
+ tempPhone = "$phoneNumPre****$phoneNumFix"
+ }
+ val content = "${ticketSize}张 $ticketName $tempPhone"
+ saveMsgBox(MsgBoxBean(
+ MsgBoxType.V2X,
+ V2XMsg(
+ EventTypeEnumNew.TYPE_VERIFICATION_SUCCESSFUL.poiType,
+ content,
+ EventTypeEnumNew.TYPE_VERIFICATION_SUCCESSFUL.tts,
+ ""
+ )
+ )
+ )
+ }
+
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/net/IBascApiService.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/net/IBascApiService.java
new file mode 100644
index 0000000000..7219cf0be7
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/net/IBascApiService.java
@@ -0,0 +1,115 @@
+package com.mogo.och.shuttle.net;
+import com.mogo.eagle.core.data.BaseData;
+import com.mogo.och.shuttle.bean.BusCloseTaskRequest;
+import com.mogo.och.shuttle.bean.BusOrdersResponse;
+import com.mogo.och.shuttle.bean.BusQueryLineTaskResponse;
+import com.mogo.och.shuttle.bean.BusQueryLinesResponse;
+import com.mogo.och.shuttle.bean.BusQueryLineStationsRequest;
+import com.mogo.och.shuttle.bean.BusRoutesResponse;
+import com.mogo.och.shuttle.bean.QueryLeaveAwayPassengersRequest;
+import com.mogo.och.shuttle.bean.QueryLeaveAwayPassengersResponse;
+import com.mogo.och.shuttle.bean.BusResetDrivingLineRequest;
+import com.mogo.och.shuttle.bean.BusUpdateSiteStatusRequest;
+import com.mogo.och.shuttle.bean.WriteOffCountResponse;
+
+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 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);
+
+
+ @Headers( {"Content-type:application/json;charset=UTF-8"} )
+ @GET("och-shuttle-cabin/api/business/v1/task/writeOffCount")
+ Observable writeOffCount(@Header ("appId") String appId, @Header("ticket") String ticket, @Query("taskId") String taskId, @Query("siteId") String siteId);
+
+}
+
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/net/OrderServiceManager.kt b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/net/OrderServiceManager.kt
new file mode 100644
index 0000000000..e305dc5c8f
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/net/OrderServiceManager.kt
@@ -0,0 +1,195 @@
+package com.mogo.och.shuttle.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.commons.storage.SharedPrefsMgr
+import com.mogo.och.common.module.constant.OchCommonConst
+import com.mogo.och.common.module.network.OchCommonServiceCallback
+import com.mogo.och.common.module.network.OchCommonSubscribeImpl
+import com.mogo.och.common.module.network.interceptor.transformIoTry
+import com.mogo.och.common.module.network.interceptor.transformTry
+import com.mogo.och.shuttle.bean.BusCloseTaskRequest
+import com.mogo.och.shuttle.bean.BusOrdersResponse
+import com.mogo.och.shuttle.bean.BusQueryLineStationsRequest
+import com.mogo.och.shuttle.bean.BusQueryLineTaskResponse
+import com.mogo.och.shuttle.bean.BusQueryLinesResponse
+import com.mogo.och.shuttle.bean.BusResetDrivingLineRequest
+import com.mogo.och.shuttle.bean.BusRoutesResponse
+import com.mogo.och.shuttle.bean.BusUpdateSiteStatusRequest
+import com.mogo.och.shuttle.bean.QueryLeaveAwayPassengersRequest
+import com.mogo.och.shuttle.bean.QueryLeaveAwayPassengersResponse
+import com.mogo.och.shuttle.bean.WriteOffCountResponse
+
+/**
+ * @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,
+ SharedPrefsMgr.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,
+ SharedPrefsMgr.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,
+ SharedPrefsMgr.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,
+ SharedPrefsMgr.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,
+ writeVersion: Long,
+ callback: OchCommonServiceCallback?
+ ) {
+ mService.leaveStation(
+ MoGoAiCloudClientConfig.getInstance().serviceAppId,
+ SharedPrefsMgr.getInstance().token,
+ BusUpdateSiteStatusRequest(taskId, siteId, seq,writeVersion)
+ )
+ .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, writeVersion: Long,
+ callback: OchCommonServiceCallback?
+ ) {
+ mService.arriveSiteStation(
+ MoGoAiCloudClientConfig.getInstance().serviceAppId,
+ SharedPrefsMgr.getInstance().token,
+ BusUpdateSiteStatusRequest(taskId, siteId, seq, writeVersion)
+ )
+ .transformTry()
+ .subscribe(OchCommonSubscribeImpl(context, callback, "arriveSiteStation"))
+ }
+
+ @JvmStatic
+ fun queryBusLines(context: Context, callback: OchCommonServiceCallback?) {
+ mService.queryBusLines(
+ MoGoAiCloudClientConfig.getInstance().serviceAppId,
+ SharedPrefsMgr.getInstance().token,
+ SharedPrefsMgr.getInstance().sn
+ )
+ .transformTry()
+ .subscribe(OchCommonSubscribeImpl(context, callback, "queryBusLines"))
+ }
+ @JvmStatic
+ fun queryBusTaskByLineId(
+ context: Context,
+ lineId: String?,
+ callback: OchCommonServiceCallback?
+ ) {
+ mService.queryBusTaskByLineId(
+ MoGoAiCloudClientConfig.getInstance().serviceAppId,
+ SharedPrefsMgr.getInstance().token,
+ lineId
+ )
+ .transformTry()
+ .subscribe(OchCommonSubscribeImpl(context, callback, "queryBusLines"))
+ }
+
+ @JvmStatic
+ fun queryBusTaskByLineId(
+ context: Context,
+ taskId: String?,
+ siteId: String?,
+ callback: OchCommonServiceCallback?
+ ) {
+ mService.writeOffCount(
+ MoGoAiCloudClientConfig.getInstance().serviceAppId,
+ SharedPrefsMgr.getInstance().token,
+ taskId,
+ siteId
+ )
+ .transformIoTry()
+ .subscribe(OchCommonSubscribeImpl(context, callback, "writeOffCount"))
+ }
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/presenter/BusLinePresenter.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/presenter/BusLinePresenter.java
new file mode 100644
index 0000000000..8dfd60efa0
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/presenter/BusLinePresenter.java
@@ -0,0 +1,115 @@
+package com.mogo.och.shuttle.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.shuttle.bean.BusQueryLineTaskResponse;
+import com.mogo.och.shuttle.bean.BusQueryLinesResponse;
+import com.mogo.och.shuttle.callback.IBusLinesCallback;
+import com.mogo.och.shuttle.model.BusLineModel;
+import com.mogo.och.shuttle.model.OrderModel;
+import com.mogo.och.shuttle.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);
+ }
+
+ @Override
+ public void onBusLinesChange(BusQueryLinesResponse lines) {
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if(mView!=null) {
+ mView.onBusLinesChange(lines);
+ }
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+ }
+
+ @Override
+ public void onChangeLineIdSuccess() {
+ OrderModel.getInstance().clearBusStationDatas();
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if(mView!=null) {
+ mView.onChangeLineIdSuccess();
+ }
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+ }
+
+ 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) {
+ if(mView!=null) {
+ mView.onBusLineTasks(o,position,autoRefresh);
+ }
+ }
+}
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/presenter/BusPresenter.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/presenter/BusPresenter.java
new file mode 100644
index 0000000000..5e055e533e
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/presenter/BusPresenter.java
@@ -0,0 +1,327 @@
+package com.mogo.och.shuttle.presenter;
+
+import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS;
+
+import android.os.Looper;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LifecycleOwner;
+
+import com.mogo.commons.AbsMogoApplication;
+import com.mogo.commons.mvp.Presenter;
+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.CallerAutoPilotControlManager;
+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.common.module.biz.login.LoginStatusEnum;
+import com.mogo.och.common.module.manager.autopilot.autopilot.ArrivedStation;
+import com.mogo.och.common.module.manager.autopilot.autopilot.IOchAutopilotStatusListener;
+import com.mogo.och.common.module.manager.autopilot.autopilot.OchAutoPilotStatusListenerManager;
+import com.mogo.och.data.bean.BusStationBean;
+import com.mogo.och.shuttle.callback.IBusADASStatusCallback;
+import com.mogo.och.shuttle.callback.IBusControllerStatusCallback;
+import com.mogo.och.shuttle.callback.IRefreshBusStationsCallback;
+import com.mogo.och.shuttle.callback.ISlidePannelHideCallback;
+import com.mogo.och.shuttle.fragment.ShuttleFragment;
+import com.mogo.och.shuttle.model.OrderModel;
+import com.mogo.och.shuttle.util.BusTrajectoryManager;
+import com.mogo.och.common.module.biz.login.ILoginCallback;
+import com.mogo.och.common.module.biz.login.LoginStatusManager;
+import com.mogo.och.common.module.manager.autopilot.OCHAdasAbilityManager;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import mogo_msg.MogoReportMsg;
+
+/**
+ * 网约车小巴
+ *
+ * @author tongchenfei
+ */
+public class BusPresenter extends Presenter
+ implements IRefreshBusStationsCallback, ISlidePannelHideCallback
+ , IOchAutopilotStatusListener, IBusControllerStatusCallback, ILoginCallback, IBusADASStatusCallback {
+
+ private static final String TAG = "BusPresenter";
+
+ private final List mStationList = new ArrayList<>();
+ private int mCurrentStation = 0;
+
+ public BusPresenter(ShuttleFragment view) {
+ super(view);
+ //2021.11.1 鹰眼架构整合,由IMoGoAutopilotStatusListener逐步替代IMogoAdasOCHCallback接口
+ OrderModel.getInstance().init();
+ OCHAdasAbilityManager.getInstance().init(AbsMogoApplication.getApp());
+
+ }
+
+ @Override
+ public void onCreate(@NonNull LifecycleOwner owner) {
+ super.onCreate(owner);
+ initModelListener();
+
+ OrderModel.getInstance().queryBusCacheRoutes();
+ }
+
+ @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().setAdasStatusCallback(this);
+ OchAutoPilotStatusListenerManager.INSTANCE.addListener(TAG,this);
+ LoginStatusManager.INSTANCE.addListener(TAG,this);
+ }
+
+ public void releaseListener() {
+ OrderModel.getInstance().setRefreshBusStationsCallback(null);
+ OrderModel.getInstance().setSlidePanelHideCallback(null);
+ OrderModel.getInstance().setControllerStatusCallback(null);
+ OrderModel.getInstance().setAdasStatusCallback(null);
+ OCHAdasAbilityManager.getInstance().release();
+ OchAutoPilotStatusListenerManager.INSTANCE.removeListener(TAG);
+ LoginStatusManager.INSTANCE.removeListener(TAG);
+ }
+
+ public void abortTask() {
+ OrderModel.getInstance().abortTask();
+ }
+
+ public void autoDriveToNextStation() {
+ OrderModel.getInstance().autoDriveToNextStation();
+ }
+
+ public void restartAutopilot() {
+ if (OrderModel.getInstance().isGoingToNextStation()){
+ OrderModel.getInstance().restartAutopilot();
+ }
+ }
+
+ // 登出
+ 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.d(M_BUS + "BusOrderModel =", " mCurrentStation =" + mCurrentStation);
+
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if(mView!=null) {
+ mView.updateBusTaskStatus(lineName,lineTime,
+ stationList, arrivingOrArrivedIndex, isArrived);
+ }
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+ }
+
+ @Override
+ public void updateEmptyUi() {
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if(mView!=null) {
+ mView.updateLineEmptyUI();
+ }
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+ }
+
+ @Override
+ public void clearBusStationsMarkers() {
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if(mView!=null) {
+ mView.clearBusStationsMarkers();
+ }
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+ }
+
+ @Override
+ public void hideSlidePanel() {
+ if (mView != null) {
+ mView.hideSlidePanel();
+ mView.setArrivedClikable(true);
+ }
+ }
+
+ @Override
+ public void onAutopilotArriveAtStation(ArrivedStation arrivedStation) {
+ CallerLogger.e( M_BUS + TAG, "行程日志-onAutopilotArriveAtStation arrive");
+ arriveStation(arrivedStation,"底盘触发进站");
+ }
+
+ public void arriveStation(ArrivedStation arrivedStation,String type){
+ OrderModel.getInstance().onArriveAt(arrivedStation,type);
+ }
+
+ @Override
+ public void onAutopilotStatusResponse(int state) {
+ switch (state) {
+ case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE:
+ case IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING:
+ case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE:
+ if (FunctionBuildConfig.isDemoMode
+ && (
+ (mCurrentStation >= 0 && mCurrentStation <= mStationList.size() - 1)
+ && OrderModel.getInstance().isGoingToNextStation()
+ )
+ ) {
+ CallerLogger.d(M_BUS + "BusOrderModel=", "有美化功能");
+ return;
+ }
+ // 改变UI自动驾驶状态
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if(mView!=null) {
+ mView.onAutopilotStatusChanged(state, CallerAutoPilotControlManager.INSTANCE.isCanStartAutopilot(false,0));
+ }
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+ break;
+ case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING:
+ OrderModel.getInstance().triggerStartServiceEvent(
+ OrderModel.getInstance().isRestartAutopilot(), true);
+ // 改变UI自动驾驶状态
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if(mView!=null) {
+ mView.onAutopilotStatusChanged(state, CallerAutoPilotControlManager.INSTANCE.isCanStartAutopilot(false,0));
+ }
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+ break;
+ default:
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if(mView!=null) {
+ mView.onAutopilotEnableChange(false);
+ }
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+ break;
+ }
+ }
+
+ @Override
+ public void onCarLocationChanged(MogoLocation location) {
+// if (null != location) {
+// runOnUIThread(() -> mView.updateSpeedView(location.getGnssSpeed()));
+// }
+ }
+
+ @Override
+ public void startOpenAutopilot() {
+ //非美化模式下启动动画
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if(mView!=null) {
+ mView.startAutopilotAnimation();
+ }
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+
+ //中间站点再次开启自驾时, 自动驾驶状态是2未改变, 此次鹰眼底层不再返给业务,需优化按钮动画显示
+ if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING
+ == CallerAutoPilotStatusListenerManager.INSTANCE.getState()&&mView!=null){
+ mView.onAutopilotStatusChanged(CallerAutoPilotStatusListenerManager.INSTANCE.getState(),
+ CallerAutoPilotControlManager.INSTANCE.isCanStartAutopilot(false,0));
+ }
+ }
+
+ private void runOnUIThread(Runnable executor) {
+ if (executor == null) {
+ return;
+ }
+ if (Looper.myLooper() != Looper.getMainLooper()) {
+ UiThreadHandler.post(executor);
+ } else {
+ executor.run();
+ }
+ }
+
+ /**
+ * 测试使用
+ */
+ public void debugAutoPilotStatus(int status) {
+ onAutopilotStatusResponse(status);
+ }
+
+
+ @Override
+ public void onAutopilotGuardian(MogoReportMsg.MogoReportMessage guardianInfo, long lineId) {
+ BusTrajectoryManager.getInstance().onAutopilotGuardian(guardianInfo,lineId);
+ }
+
+ @Override
+ public void onStatusChange(LoginStatusEnum currentStatus) {
+ ILoginCallback.super.onStatusChange(currentStatus);
+ CallerLogger.d(M_BUS + TAG, " loginStatus =" + LoginStatusManager.isLogin());
+ if(LoginStatusManager.isLogin()){
+// OrderModel.getInstance().queryBusRoutes();
+ OrderModel.getInstance().queryBusCacheRoutes();
+ }else {
+ BusTrajectoryManager.getInstance().stopTrajReqLoop();
+ BusTrajectoryManager.getInstance().stopTrajReqLoop();
+ clearBusStationsMarkers();
+ if(mView!=null) {
+ mView.hideSlidePanel();
+ }
+ OrderModel.getInstance().closeBeautificationMode();
+ }
+ }
+
+ @Override
+ public void onStartAdasFailure() {
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if(mView!=null) {
+ mView.stopAnimAndUpdateBtnStatus();
+ }
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+ }
+
+ @Override
+ public void canStartAutopilot(boolean canStart) {
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if(mView!=null) {
+ mView.onAutopilotStatusChanged(CallerAutoPilotStatusListenerManager.INSTANCE.getState(),canStart);
+ }
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+ }
+}
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ui/BusStationCommonItem.kt b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ui/BusStationCommonItem.kt
new file mode 100644
index 0000000000..9f6c121f07
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ui/BusStationCommonItem.kt
@@ -0,0 +1,99 @@
+package com.mogo.och.shuttle.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.shuttle.R
+import com.mogo.och.common.module.utils.BlinkAnimationUtil
+import kotlinx.android.synthetic.main.shuttle_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.shuttle_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/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ui/BusSwitchLineActivity.kt b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ui/BusSwitchLineActivity.kt
new file mode 100644
index 0000000000..a9fddd0ff4
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ui/BusSwitchLineActivity.kt
@@ -0,0 +1,222 @@
+package com.mogo.och.shuttle.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.commons.storage.SharedPrefsMgr
+import com.mogo.och.shuttle.presenter.BusLinePresenter
+import com.mogo.och.shuttle.ui.adapter.SwitchLineAdapter
+import com.mogo.och.shuttle.bean.BusQueryLinesResponse
+import com.mogo.och.shuttle.ui.adapter.OpenItemAnimator
+import com.mogo.eagle.core.utilcode.mogo.view.SpacesItemDecoration
+import com.mogo.eagle.core.utilcode.util.ToastUtils
+import com.mogo.och.shuttle.R
+import com.mogo.och.shuttle.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.shuttle_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
+ }
+ val lastCommitLineid = SharedPrefsMgr.getInstance().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/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ui/BusSwitchLineView.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ui/BusSwitchLineView.java
new file mode 100644
index 0000000000..5a4d85d312
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ui/BusSwitchLineView.java
@@ -0,0 +1,18 @@
+package com.mogo.och.shuttle.ui;
+
+import com.mogo.commons.mvp.IView;
+import com.mogo.och.shuttle.bean.BusQueryLineTaskResponse;
+import com.mogo.och.shuttle.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/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ui/adapter/OpenItemAnimator.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ui/adapter/OpenItemAnimator.java
new file mode 100644
index 0000000000..bc8596d255
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ui/adapter/OpenItemAnimator.java
@@ -0,0 +1,643 @@
+package com.mogo.och.shuttle.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 final ArrayList mPendingRemovals = new ArrayList<>();
+ private final ArrayList mPendingAdditions = new ArrayList<>();
+ private final ArrayList mPendingMoves = new ArrayList<>();
+ private final 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<>(mPendingMoves);
+ mMovesList.add(moves);
+ mPendingMoves.clear();
+ Runnable mover = () -> {
+ 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<>(mPendingChanges);
+ mChangesList.add(changes);
+ mPendingChanges.clear();
+ Runnable changer = () -> {
+ 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<>(mPendingAdditions);
+ mAdditionsList.add(additions);
+ mPendingAdditions.clear();
+ Runnable adder = () -> {
+ 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((float)(changeInfo.toX - changeInfo.fromX));
+ oldViewAnim.translationY((float)(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/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ui/adapter/SwitchLineAdapter.kt b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ui/adapter/SwitchLineAdapter.kt
new file mode 100644
index 0000000000..19738350eb
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ui/adapter/SwitchLineAdapter.kt
@@ -0,0 +1,181 @@
+package com.mogo.och.shuttle.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.shuttle.R
+import com.mogo.och.shuttle.bean.BusQueryLinesResponse
+import com.mogo.och.shuttle.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.shuttle_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) {
+ try {
+ if(isCheck) {
+ checkLineId = line.lineId
+ checkTaskId = line.taskList[position].id
+ }else{
+ checkLineId=-1
+ checkTaskId=-1
+ }
+ }catch (e:Exception){
+ e.printStackTrace()
+ 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/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ui/adapter/SwitchLineTaskAdapter.kt b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ui/adapter/SwitchLineTaskAdapter.kt
new file mode 100644
index 0000000000..95d5badfb8
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ui/adapter/SwitchLineTaskAdapter.kt
@@ -0,0 +1,76 @@
+package com.mogo.och.shuttle.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.shuttle.R
+import com.mogo.och.shuttle.bean.BusQueryLineTaskResponse
+import com.mogo.och.shuttle.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.shuttle_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/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ui/writeoff/WriteOffView.kt b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ui/writeoff/WriteOffView.kt
new file mode 100644
index 0000000000..b0d7b3851a
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ui/writeoff/WriteOffView.kt
@@ -0,0 +1,55 @@
+package com.mogo.och.shuttle.ui.writeoff
+
+import android.content.Context
+import android.util.AttributeSet
+import android.util.Log
+import android.view.LayoutInflater
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.lifecycle.ViewModelProvider
+import androidx.lifecycle.findViewTreeViewModelStoreOwner
+import com.mogo.och.shuttle.R
+import kotlinx.android.synthetic.main.shuttle_wirte_off_view.view.tv_write_off_count
+
+class WriteOffView : ConstraintLayout, WriteOffViewModel.IwriteOffViewCallback {
+
+ private val TAG = "ItineraryView"
+
+ constructor(context: Context) : super(context)
+
+ constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet)
+
+ constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int) : super(context, attributeSet, defStyleAttr)
+
+ constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attributeSet, defStyleAttr, defStyleRes)
+
+ private fun initView() {
+ LayoutInflater.from(context).inflate(R.layout.shuttle_wirte_off_view, this, true)
+ }
+
+
+
+ override fun onAttachedToWindow() {
+ super.onAttachedToWindow()
+
+ val viewModel = findViewTreeViewModelStoreOwner()?.let {
+ ViewModelProvider(it).get(WriteOffViewModel::class.java)
+ }
+
+ viewModel?.setWriteOffCallback(this)
+ }
+
+
+ init {
+ try {
+ initView()
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ }
+
+ override fun setWriteOffCount(showText: String) {
+ tv_write_off_count.text = showText
+ }
+
+
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ui/writeoff/WriteOffViewModel.kt b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ui/writeoff/WriteOffViewModel.kt
new file mode 100644
index 0000000000..27953a4012
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/ui/writeoff/WriteOffViewModel.kt
@@ -0,0 +1,70 @@
+package com.mogo.och.shuttle.ui.writeoff
+
+import androidx.lifecycle.ViewModel
+import com.mogo.commons.AbsMogoApplication
+import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
+import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
+import com.mogo.och.shuttle.R
+import com.mogo.och.shuttle.model.TicketModel
+import com.mogo.och.common.module.utils.RxUtils
+import io.reactivex.Observable
+import io.reactivex.Observer
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.Disposable
+
+class WriteOffViewModel : ViewModel() {
+
+ private val TAG = WriteOffViewModel::class.java.simpleName
+
+ private var viewCallback: IwriteOffViewCallback? = null
+
+ init {
+
+ }
+
+ private var disposable: Disposable? = null
+
+ private val observer = object : Observer {
+ override fun onSubscribe(d: Disposable) {
+ disposable = d
+ }
+
+ override fun onError(e: Throwable) {
+
+ }
+
+ override fun onComplete() {
+
+ }
+
+ override fun onNext(countInfo: String) {
+ viewCallback?.setWriteOffCount(countInfo)
+ }
+
+ }
+
+ fun setWriteOffCallback(viewCallback: IwriteOffViewCallback) {
+ this.viewCallback = viewCallback
+ TicketModel
+ .getWriteOffCountObservable()
+ .flatMap { t ->
+ val showText =
+ AbsMogoApplication.getApp().getString(R.string.shuttle_write_off_count, t)
+ CallerLogger.d(SceneConstant.M_BUS + TAG, "显示文案:${showText}")
+ Observable.just(showText)
+ }
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(observer)
+ }
+
+ override fun onCleared() {
+ super.onCleared()
+ this.viewCallback = null
+ RxUtils.disposeSubscribe(disposable)
+ }
+
+ interface IwriteOffViewCallback {
+ fun setWriteOffCount(count:String)
+ }
+
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/util/BusAnalyticsManager.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/util/BusAnalyticsManager.java
new file mode 100644
index 0000000000..5e85fa7ffa
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/util/BusAnalyticsManager.java
@@ -0,0 +1,56 @@
+package com.mogo.och.shuttle.util;
+
+
+import androidx.annotation.NonNull;
+
+import com.mogo.och.common.module.manager.autopilot.autopilot.OchAutopilotAnalytics;
+
+/**
+ * OCH Bus埋点工具
+ *
+ * Created on 2022/3/24
+ */
+public class BusAnalyticsManager extends OchAutopilotAnalytics {
+
+ // 埋点key:开启自动驾驶前已识别的异常,会导致无法开启自驾
+ private static final String EVENT_KEY_AP_UNABLE_START_REASON = "event_key_och_bus_ap_unable_start_reason";
+ // 埋点key:接管后点击'自动驾驶'按钮启动
+ private static final String EVENT_KEY_RESTART_AUTOPILOT = "event_key_och_bus_restart_autopilot";
+ // 埋点key:开始服务开启自动驾驶(成功/失败)
+ private static final String EVENT_KEY_START_SERVICE = "event_key_och_bus_start_service";
+ // 埋点key:点击启动自驾
+ private static final String EVENT_KEY_CLICK_START_AUTOPILOT = "event_key_och_shuttle_click_start_autopilot";
+
+ private static final class SingletonHolder {
+ private static final BusAnalyticsManager INSTANCE = new BusAnalyticsManager();
+ }
+
+ public static BusAnalyticsManager getInstance() {
+ return BusAnalyticsManager.SingletonHolder.INSTANCE;
+ }
+
+ @NonNull
+ @Override
+ public String getEventKeyStartService() {
+ return EVENT_KEY_START_SERVICE;
+ }
+
+ @NonNull
+ @Override
+ public String getEventKeyRestartService() {
+ return EVENT_KEY_RESTART_AUTOPILOT;
+ }
+
+ @NonNull
+ @Override
+ public String getEventKeyApUnableStartReason() {
+ return EVENT_KEY_AP_UNABLE_START_REASON;
+ }
+
+ @NonNull
+ @Override
+ public String getEventKeyClickStartAutopilot() {
+ return EVENT_KEY_CLICK_START_AUTOPILOT;
+ }
+
+}
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/util/BusSendTripInfoManager.kt b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/util/BusSendTripInfoManager.kt
new file mode 100644
index 0000000000..51fb81a0d0
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/util/BusSendTripInfoManager.kt
@@ -0,0 +1,36 @@
+package com.mogo.och.shuttle.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/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/util/BusTrajectoryManager.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/util/BusTrajectoryManager.java
new file mode 100644
index 0000000000..2154ea4672
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/util/BusTrajectoryManager.java
@@ -0,0 +1,204 @@
+package com.mogo.och.shuttle.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.common.module.manager.logchainanalytic.OchChainLogManager;
+import com.mogo.och.data.bean.BusRoutesResult;
+import com.mogo.och.shuttle.constant.BusConst;
+import com.mogo.och.shuttle.model.OrderModel;
+import com.mogo.och.common.module.biz.login.LoginStatusManager;
+
+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.d(M_BUS + TAG, "syncTrajectoryInfo() start.");
+ startTrajReqLoop();
+ } else {
+ // 无路线信息or当前未在始发站
+ CallerLogger.d(M_BUS + TAG, "syncTrajectoryInfo() stop.");
+ stopTrajReqLoop();
+ }
+ }
+
+ public void onAutopilotGuardian(@Nullable MogoReportMsg.MogoReportMessage guardianInfo,long lineId) {
+ onAutopilotGuardian(guardianInfo);
+ }
+
+ /**
+ * 接口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.d(M_BUS + TAG, "onAutopilotGuardian() 轨迹开始下载");
+ OchChainLogManager.writeChainLog("轨迹监控","onAutopilotGuardian() 轨迹开始下载", true, OchChainLogManager.EVENT_KEY_INFE_WITH_TRAJECTORY);
+ // ToastUtils.showShort("轨迹开始下载");
+ stopTrajReqLoop();
+ } else if ("ISYS_INIT_TRAJECTORY_SUCCESS".equals(guardianInfo.getCode())) {
+ // 2. 轨迹管理_轨迹下载成功(本地已有对应轨迹也触发)
+ CallerLogger.d(M_BUS + TAG, "onAutopilotGuardian() 轨迹下载成功");
+ OchChainLogManager.writeChainLog("轨迹监控","onAutopilotGuardian() 轨迹下载成功", true, OchChainLogManager.EVENT_KEY_INFE_WITH_TRAJECTORY);
+ // ToastUtils.showShort("轨迹下载成功");
+ stopTrajReqLoop();
+ } else if ("ISYS_INIT_TRAJECTORY_FAILURE".equals(guardianInfo.getCode())) {
+ // 3. 轨迹管理_轨迹下载失败,本地无对应轨迹
+ CallerLogger.d(M_BUS + TAG, "onAutopilotGuardian() " +
+ "轨迹下载失败,本地无对应轨迹");
+ OchChainLogManager.writeChainLog("轨迹监控","onAutopilotGuardian() 轨迹下载失败,本地无对应轨迹", true, OchChainLogManager.EVENT_KEY_INFE_WITH_TRAJECTORY);
+ // ToastUtils.showShort("轨迹下载失败,本地无对应轨迹");
+ } else if ("ISYS_INIT_TRAJECTORY_WARNING".equals(guardianInfo.getCode())) {
+ // 4. 轨迹管理_轨迹下载失败,本地有对应轨迹,认为成功
+ CallerLogger.d(M_BUS + TAG, "onAutopilotGuardian() " +
+ "轨迹下载失败,本地有对应轨迹,认为成功");
+ OchChainLogManager.writeChainLog("轨迹监控","onAutopilotGuardian() 轨迹下载失败,本地有对应轨迹,认为成功", true, OchChainLogManager.EVENT_KEY_INFE_WITH_TRAJECTORY);
+ // ToastUtils.showShort("轨迹下载失败,本地有对应轨迹,认为成功");
+ } else if ("ISYS_INIT_TRAJECTORY_TIMEOUT".equals(guardianInfo.getCode())) {
+ // 5. 轨迹管理_轨迹下载超时
+ CallerLogger.d(M_BUS + TAG, "onAutopilotGuardian() 轨迹下载超时");
+ OchChainLogManager.writeChainLog("轨迹监控","onAutopilotGuardian() 轨迹下载超时", true, OchChainLogManager.EVENT_KEY_INFE_WITH_TRAJECTORY);
+ // ToastUtils.showShort("轨迹下载超时");
+ } else if ("ISSM_FUNC_AUTO_PILOT_READY".equals(guardianInfo.getCode())) {
+ // 收到ssm的自动驾驶变为ready,再次下发轨迹下载.解决:域控重启,或者102域控启动太早,107节点初始化未完成导致的轨迹未进行下载。
+ CallerLogger.d(M_BUS + TAG, "onAutopilotGuardian() ssm ready,再次发起下载");
+ OchChainLogManager.writeChainLog("轨迹监控","onAutopilotGuardian() 再次发起下载", true, OchChainLogManager.EVENT_KEY_INFE_WITH_TRAJECTORY);
+ syncTrajectoryInfo();
+ }
+ }
+
+ private void setupAutoPilotLine() {
+ BusRoutesResult routesResult = OrderModel.getInstance().getBusRoutesResult();
+ if (routesResult == null) {
+ CallerLogger.e(M_BUS + TAG,
+ "setupAutoPilotLine(): routesResult is null.");
+ return;
+ } else {
+ if (mAutoPilotLine == null) {
+ mAutoPilotLine = new AutopilotControlParameters.AutoPilotLine(
+ routesResult.getLineId(), routesResult.getName(),
+ 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.setLineName(routesResult.getName());
+ 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.setLineName("");
+ 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.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.d(M_BUS + TAG, "loop sendTrajectoryReq: " + aLong);
+ sendTrajectoryReq();
+ });
+ }
+
+ public void stopTrajReqLoop() {
+ if (mSendReqDisposable != null) {
+ CallerLogger.d(M_BUS + TAG, "stopTrajReqLoop()");
+ mSendReqDisposable.dispose();
+ mSendReqDisposable = null;
+ clearAutoPilotLine();
+ }
+ }
+
+ private void sendTrajectoryReq() {
+ if (mAutoPilotLine == null) {
+ CallerLogger.e(M_BUS + TAG, "sendTrajectoryReq(): mAutoPilotLine is null!!!");
+ return;
+ }
+ OchChainLogManager.writeChainLog("轨迹监控","sendTrajectoryReq() 下发轨迹 轨迹id"+mAutoPilotLine.getLineId(), true, OchChainLogManager.EVENT_KEY_INFE_WITH_TRAJECTORY);
+ CallerAutoPilotControlManager.INSTANCE.sendTrajectoryDownloadReq(mAutoPilotLine);
+ CallerLogger.d(M_BUS + TAG, "sendTrajectoryReq(): "
+ + GsonUtils.toJson(mAutoPilotLine));
+ }
+}
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/util/ShuttleVoiceManager.kt b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/util/ShuttleVoiceManager.kt
new file mode 100644
index 0000000000..854c739097
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/util/ShuttleVoiceManager.kt
@@ -0,0 +1,93 @@
+package com.mogo.och.shuttle.util
+
+import com.mogo.commons.AbsMogoApplication
+import com.mogo.commons.voice.AIAssist
+import com.mogo.eagle.core.data.config.FunctionBuildConfig
+import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
+import com.mogo.och.shuttle.R
+import com.mogo.och.common.module.voice.VoiceNotice
+import com.mogo.tts.base.LangTtsEntity
+import com.mogo.tts.base.LanguageType
+import java.util.ArrayList
+
+object ShuttleVoiceManager {
+
+ fun arrivedStationBus(siteNameCN: String?, siteNameKR: String?) {
+ val context = AbsMogoApplication.getApp()
+ val list: MutableList = ArrayList()
+ siteNameCN?.let {
+ val chineseTTS = LangTtsEntity(
+ context.getString(R.string.bus_arrived_station_tip, it),
+ LanguageType.CHINESE
+ )
+ val engTTS = LangTtsEntity(
+ context.getString(R.string.bus_arrived_station_english_tip, it),
+ LanguageType.ENGLISH
+ )
+ val koreanTTS = LangTtsEntity(
+ context.getString(R.string.bus_arrived_station_korean_tip, siteNameKR?:it),
+ LanguageType.KOREAN
+ )
+ list.add(chineseTTS)
+ list.add(engTTS)
+ list.add(koreanTTS)
+ }
+
+ VoiceNotice.showNotice(list, AIAssist.LEVEL1,null)
+ }
+
+ fun leaveStationBus(siteNameCN: String?, siteNameKR: String?) {
+ val list: MutableList = ArrayList()
+ val context = AbsMogoApplication.getApp()
+ siteNameCN?.let {
+ val chineseTTS = LangTtsEntity(
+ context.getString(R.string.bus_leave_station_tip, it),
+ LanguageType.CHINESE
+ )
+ val engTTS = LangTtsEntity(
+ context.getString(R.string.bus_leave_station_english_tip, it),
+ LanguageType.ENGLISH
+ )
+ list.add(chineseTTS)
+ list.add(engTTS)
+
+ val koreanTTS = LangTtsEntity(
+ context.getString(R.string.bus_leave_station_korean_tip, siteNameKR ?: it),
+ LanguageType.KOREAN
+ )
+ list.add(koreanTTS)
+ }
+ VoiceNotice.showNotice(list, AIAssist.LEVEL1,null)
+ }
+
+ fun endOrderBus() {
+ val context = AbsMogoApplication.getApp()
+ val list: MutableList = ArrayList()
+ val chineseTTS = LangTtsEntity(context.getString(R.string.bus_end_task_tip), LanguageType.CHINESE)
+ val engTTS = LangTtsEntity(context.getString(R.string.bus_end_task_english_tip), LanguageType.ENGLISH)
+ val koreanTTS = LangTtsEntity(context.getString(R.string.bus_end_task_korean_tip), LanguageType.KOREAN)
+ list.add(chineseTTS)
+ list.add(engTTS)
+ list.add(koreanTTS)
+ VoiceNotice.showNotice(list, AIAssist.LEVEL0,null)
+ }
+
+ fun writeOffCount(successNum:Int){
+ if(successNum<=1){
+ VoiceNotice.showNotice("核验通过", AIAssist.LEVEL3);
+ }else{
+ VoiceNotice.showNotice("$successNum 人核验通过", AIAssist.LEVEL3)
+ }
+ }
+
+ // 距离发车还有1分钟
+ fun showLeafTime(tips: String) {
+ //语音提示
+ VoiceNotice.showNotice(tips)
+ }
+
+ fun writeOffFaile(reaseon:String) {
+ VoiceNotice.showNotice("验票失败,${reaseon}", AIAssist.LEVEL3)
+ }
+
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/view/BizMapView.kt b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/view/BizMapView.kt
new file mode 100644
index 0000000000..d396c664ca
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/view/BizMapView.kt
@@ -0,0 +1,63 @@
+package com.mogo.och.shuttle.view
+
+import android.content.Context
+import android.os.Bundle
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.widget.FrameLayout
+import com.mogo.eagle.core.data.config.FunctionBuildConfig
+import com.mogo.eagle.core.function.view.MapBizView
+import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
+import com.mogo.map.uicontroller.IMogoMapUIController
+import com.mogo.och.shuttle.R
+
+/**
+ * 魔戒蓝牙控件
+ * 放置于StatusBar右侧位置
+ */
+class BizMapView @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0
+) : FrameLayout(context, attrs, defStyleAttr) {
+
+ private lateinit var mapBizView: MapBizView
+
+ init {
+ if (AppIdentityModeUtils.isB2(FunctionBuildConfig.appIdentityMode)) {
+ LayoutInflater.from(context).inflate(R.layout.shuttle_m2_bizmap_map, this, true)
+ }else if(AppIdentityModeUtils.isB1(FunctionBuildConfig.appIdentityMode)){
+ LayoutInflater.from(context).inflate(R.layout.shuttle_jl_bizmap_map, this, true)
+ }else{
+ LayoutInflater.from(context).inflate(R.layout.shuttle_jl_bizmap_map, this, true)
+ }
+ mapBizView = findViewById(R.id.bizMapView)
+ }
+
+ fun getUI(): IMogoMapUIController? {
+ return mapBizView.getUI()
+ }
+
+ fun onCreate(bundle: Bundle?) {
+ mapBizView.onCreate(bundle)
+ }
+ fun onResume() {
+ mapBizView.onResume()
+ }
+
+ fun onSaveInstanceState(outState: Bundle){
+ mapBizView.onSaveInstanceState(outState)
+ }
+
+ fun onLowMemory() {
+ mapBizView.onLowMemory()
+ }
+
+ fun onPause() {
+ mapBizView.onPause()
+ }
+
+ fun onDestroy() {
+ mapBizView.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/view/SlidePanelView.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/view/SlidePanelView.java
new file mode 100644
index 0000000000..87c355ceb5
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/view/SlidePanelView.java
@@ -0,0 +1,300 @@
+package com.mogo.och.shuttle.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.ConvertUtils;
+import com.mogo.eagle.core.utilcode.util.ThreadUtils;
+import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
+import com.mogo.och.shuttle.R;
+import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager;
+
+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 final 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);
+ decodeImage();
+ }
+
+ private void decodeImage(){
+ ThreadUtils.getCpuPool().execute(() -> {
+ 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();
+ UiThreadHandler.post(this::requestLayout,UiThreadHandler.MODE.QUEUE);
+ });
+ }
+
+ @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(bmBlock!=null) {
+ 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;
+ }
+
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ // 画背景
+ canvas.drawRoundRect(bgRectF, (float) getHeight() / 2.0f, (float) getHeight() / 2.0f, bgPaint);
+ // 画文字
+ gradientMatrix.setTranslate(matrixTranslate, 0);
+ textGradient.setLocalMatrix(gradientMatrix);
+ canvas.save();
+ canvas.drawText(blockText, (float) (blockWidth + BLOCK_START_X + textMarginLeft), (float) textOffset, textPaint);
+ canvas.restore();
+ if (bmBlock != null) {
+ if(bmBlock.getByteCount()>=5*1024*1024){
+ OchChainLogManager.writeChainLog("崩溃兜底策略",
+ "图片大小监听"+ ConvertUtils.byte2FitMemorySize(bmBlock.getByteCount()),true,OchChainLogManager.EVENT_KEY_INFE_ERROR);
+ bmBlock.recycle();
+ bmBlock = null;
+ blockWidth = 0;
+ decodeImage();
+ }else {
+ // 画滑块
+ canvas.drawBitmap(bmBlock, (float) (BLOCK_START_X + blockOffset), (float) BLOCK_START_Y, blockPaint);
+ }
+ }
+
+ }
+
+ public interface OnSlidePanelMoveToEndListener {
+ /**
+ * 滑块滑到了末尾
+ */
+ void moveToEnd();
+ }
+}
diff --git a/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/view/VerticalDashLineView.java b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/view/VerticalDashLineView.java
new file mode 100644
index 0000000000..2b0fdfcf6d
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/java/com/mogo/och/shuttle/view/VerticalDashLineView.java
@@ -0,0 +1,64 @@
+package com.mogo.och.shuttle.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/shuttle_weaknet/driver/src/main/res/color/bus_autopilot_text_color_selector.xml b/OCH/shuttle_weaknet/driver/src/main/res/color/bus_autopilot_text_color_selector.xml
new file mode 100644
index 0000000000..15f6897792
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/color/bus_autopilot_text_color_selector.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_base_icon_in_autopilot.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_base_icon_in_autopilot.png
new file mode 100644
index 0000000000..75c26c3d71
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_base_icon_in_autopilot.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_base_icon_not_in_autopilot.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_base_icon_not_in_autopilot.png
new file mode 100644
index 0000000000..927296d690
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_base_icon_not_in_autopilot.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_base_slide_block.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_base_slide_block.png
new file mode 100644
index 0000000000..ed7b293b90
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_base_slide_block.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_disable_autopilot_icon.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_disable_autopilot_icon.png
new file mode 100644
index 0000000000..170f254cd1
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_disable_autopilot_icon.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_dot_line.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_dot_line.png
new file mode 100644
index 0000000000..186001352c
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_dot_line.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_ic_autopilot.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_ic_autopilot.png
new file mode 100644
index 0000000000..be978145dc
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_ic_autopilot.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_icon_arrived_station.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_icon_arrived_station.png
new file mode 100644
index 0000000000..8a065b66dd
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_icon_arrived_station.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_icon_arriving_station.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_icon_arriving_station.png
new file mode 100644
index 0000000000..4ed57a0e30
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_icon_arriving_station.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_icon_not_arrive_station.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_icon_not_arrive_station.png
new file mode 100644
index 0000000000..e0bb24c526
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_icon_not_arrive_station.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_light_green_nor.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_light_green_nor.png
new file mode 100644
index 0000000000..bc9fed952d
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_light_green_nor.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_light_red_nor.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_light_red_nor.png
new file mode 100644
index 0000000000..8732508ded
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_light_red_nor.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_lightyellow_nor.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_lightyellow_nor.png
new file mode 100644
index 0000000000..bae01408fd
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_lightyellow_nor.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_line_panel_bg.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_line_panel_bg.png
new file mode 100755
index 0000000000..3166d20e37
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_line_panel_bg.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_line_panel_bg_1.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_line_panel_bg_1.png
new file mode 100755
index 0000000000..09a9c252da
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_line_panel_bg_1.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_line_task_arrow.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_line_task_arrow.png
new file mode 100644
index 0000000000..b32f0693a6
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_line_task_arrow.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_loading_autopilot_icon.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_loading_autopilot_icon.png
new file mode 100644
index 0000000000..f21a1081f1
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_loading_autopilot_icon.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_no_line_icon.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_no_line_icon.png
new file mode 100755
index 0000000000..fc20dca73c
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_no_line_icon.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_och_dot_line.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_och_dot_line.png
new file mode 100644
index 0000000000..a720a532ea
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_och_dot_line.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_operation_status_bg.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_operation_status_bg.png
new file mode 100644
index 0000000000..3c339efde4
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_operation_status_bg.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_operation_status_select_bg.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_operation_status_select_bg.png
new file mode 100644
index 0000000000..c6717d2518
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_operation_status_select_bg.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_right_autopilot_icon.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_right_autopilot_icon.png
new file mode 100644
index 0000000000..cc2b18083d
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_right_autopilot_icon.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_selected_btn.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_selected_btn.png
new file mode 100644
index 0000000000..3f05565483
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_selected_btn.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_setting_btn_bg.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_setting_btn_bg.png
new file mode 100644
index 0000000000..ba41bf3a53
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_setting_btn_bg.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_switch_line_close.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_switch_line_close.png
new file mode 100644
index 0000000000..370b61de38
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_switch_line_close.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_switch_map_long.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_switch_map_long.png
new file mode 100755
index 0000000000..cf3e5a3778
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_switch_map_long.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_switch_map_medium.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_switch_map_medium.png
new file mode 100755
index 0000000000..bdc2725468
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_switch_map_medium.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_unselect_btn.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_unselect_btn.png
new file mode 100644
index 0000000000..0114bb4f2b
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_unselect_btn.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_wrong_autopilot_icon.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_wrong_autopilot_icon.png
new file mode 100644
index 0000000000..0c8988acb3
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/bus_wrong_autopilot_icon.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/end_maker_icon.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/end_maker_icon.png
new file mode 100755
index 0000000000..8acf113151
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/end_maker_icon.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_ai_collect.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_ai_collect.png
new file mode 100755
index 0000000000..6da7b81fe4
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_ai_collect.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_ai_normal.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_ai_normal.png
new file mode 100755
index 0000000000..e98738b192
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_ai_normal.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_ai_select.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_ai_select.png
new file mode 100755
index 0000000000..d3e0107c02
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_ai_select.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_arrow_blue_bus.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_arrow_blue_bus.png
new file mode 100755
index 0000000000..026c36086f
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_arrow_blue_bus.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_arrow_green_bus.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_arrow_green_bus.png
new file mode 100755
index 0000000000..06bebc7013
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_arrow_green_bus.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_arrow_grey_bus.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_arrow_grey_bus.png
new file mode 100755
index 0000000000..f4f9b2bca2
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_arrow_grey_bus.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_bad_case.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_bad_case.png
new file mode 100755
index 0000000000..22f88301f9
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_bad_case.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_bad_case_normal.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_bad_case_normal.png
new file mode 100755
index 0000000000..c0a978fc2b
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_bad_case_normal.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_bad_case_select.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_bad_case_select.png
new file mode 100755
index 0000000000..ebacf3a11a
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_bad_case_select.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_no_bus_line.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_no_bus_line.png
new file mode 100755
index 0000000000..fc20dca73c
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_no_bus_line.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_point_blue_bus.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_point_blue_bus.png
new file mode 100755
index 0000000000..dc4c4f6f0d
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_point_blue_bus.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_point_green_bus.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_point_green_bus.png
new file mode 100755
index 0000000000..ed3b871338
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_point_green_bus.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_point_grey_bus.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_point_grey_bus.png
new file mode 100755
index 0000000000..d43e34bb26
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_point_grey_bus.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_station_start_end.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_station_start_end.png
new file mode 100644
index 0000000000..04580a8f0d
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/icon_station_start_end.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/no_order_data.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/no_order_data.png
new file mode 100644
index 0000000000..0e61996d3f
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/no_order_data.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/pingxingjiashi.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/pingxingjiashi.png
new file mode 100644
index 0000000000..78bfa2687f
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/pingxingjiashi.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/press_start_status.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/press_start_status.png
new file mode 100755
index 0000000000..af32c20cb5
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/press_start_status.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/shuttle_write_off_bg.png b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/shuttle_write_off_bg.png
new file mode 100755
index 0000000000..de9b6c49b7
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/drawable-nodpi/shuttle_write_off_bg.png differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable/ai_collect_selector.xml b/OCH/shuttle_weaknet/driver/src/main/res/drawable/ai_collect_selector.xml
new file mode 100755
index 0000000000..a1211f3c47
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/drawable/ai_collect_selector.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable/bad_case_selector.xml b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bad_case_selector.xml
new file mode 100755
index 0000000000..bc47ce95d7
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bad_case_selector.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable/bg_bus_traffic_light_background.xml b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bg_bus_traffic_light_background.xml
new file mode 100644
index 0000000000..e0b90b9c55
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bg_bus_traffic_light_background.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_autopilot_0_1_status_bg.xml b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_autopilot_0_1_status_bg.xml
new file mode 100644
index 0000000000..47ca8c7d4b
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_autopilot_0_1_status_bg.xml
@@ -0,0 +1,8 @@
+
+
+ -
+
+ -
+
+
+
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_base_autopilot_status_icon_selector.xml b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_base_autopilot_status_icon_selector.xml
new file mode 100644
index 0000000000..94555d78cc
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/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/shuttle_weaknet/driver/src/main/res/drawable/bus_checkbox_selector.xml b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_checkbox_selector.xml
new file mode 100644
index 0000000000..d95e931160
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_checkbox_selector.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_line_dividing_line1_selector.xml b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_line_dividing_line1_selector.xml
new file mode 100644
index 0000000000..b00fbd8bd6
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_line_dividing_line1_selector.xml
@@ -0,0 +1,8 @@
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_line_dividing_line2_selector.xml b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_line_dividing_line2_selector.xml
new file mode 100644
index 0000000000..ee555aae15
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_line_dividing_line2_selector.xml
@@ -0,0 +1,8 @@
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_operation_status_bg_selector.xml b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_operation_status_bg_selector.xml
new file mode 100755
index 0000000000..3a3dc6a292
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_operation_status_bg_selector.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_panel_anchor_bkg.xml b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_panel_anchor_bkg.xml
new file mode 100644
index 0000000000..21b39b7e37
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_panel_anchor_bkg.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_panel_bkg.xml b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_panel_bkg.xml
new file mode 100644
index 0000000000..69539ed40f
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_panel_bkg.xml
@@ -0,0 +1,19 @@
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_setting_tip_red_cir_bg.xml b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_setting_tip_red_cir_bg.xml
new file mode 100644
index 0000000000..203971340e
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/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/shuttle_weaknet/driver/src/main/res/drawable/bus_shape_select_line_item_bg_normal.xml b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_shape_select_line_item_bg_normal.xml
new file mode 100644
index 0000000000..272e718cce
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/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/shuttle_weaknet/driver/src/main/res/drawable/bus_shape_select_line_item_bg_selected.xml b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_shape_select_line_item_bg_selected.xml
new file mode 100644
index 0000000000..e5faafb27b
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/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/shuttle_weaknet/driver/src/main/res/drawable/bus_shape_select_line_item_time_bg.xml b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_shape_select_line_item_time_bg.xml
new file mode 100644
index 0000000000..ee8088637c
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/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/shuttle_weaknet/driver/src/main/res/drawable/bus_shape_select_line_item_time_bg_selected.xml b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_shape_select_line_item_time_bg_selected.xml
new file mode 100644
index 0000000000..e2b482ee5f
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/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/shuttle_weaknet/driver/src/main/res/drawable/bus_station_green_dash_line.xml b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_station_green_dash_line.xml
new file mode 100644
index 0000000000..fe46ef2228
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_station_green_dash_line.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_station_v_green_dash.xml b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_station_v_green_dash.xml
new file mode 100644
index 0000000000..376e0a472c
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_station_v_green_dash.xml
@@ -0,0 +1,11 @@
+
+
+ -
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_switch_line_btn.xml b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_switch_line_btn.xml
new file mode 100644
index 0000000000..8b066b0ce8
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_switch_line_btn.xml
@@ -0,0 +1,11 @@
+
+
+ -
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_switch_line_btn_commit.xml b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_switch_line_btn_commit.xml
new file mode 100644
index 0000000000..e94992d507
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_switch_line_btn_commit.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_switch_map_bg.xml b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_switch_map_bg.xml
new file mode 100644
index 0000000000..b34021d977
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_switch_map_bg.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_task_time_bg.xml b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_task_time_bg.xml
new file mode 100644
index 0000000000..917f3932fe
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_task_time_bg.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_yi_biao_pan_bg_nor.xml b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_yi_biao_pan_bg_nor.xml
new file mode 100644
index 0000000000..2ef90e60f7
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/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/shuttle_weaknet/driver/src/main/res/drawable/bus_yi_biao_pan_bg_speeding.xml b/OCH/shuttle_weaknet/driver/src/main/res/drawable/bus_yi_biao_pan_bg_speeding.xml
new file mode 100644
index 0000000000..dea7a88bb6
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/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/shuttle_weaknet/driver/src/main/res/layout/shuttle_base_fragment.xml b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_base_fragment.xml
new file mode 100644
index 0000000000..159ebca0d0
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_base_fragment.xml
@@ -0,0 +1,379 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_fragment_och.xml b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_fragment_och.xml
new file mode 100644
index 0000000000..e5b1c21ffb
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_fragment_och.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_jl_bizmap_map.xml b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_jl_bizmap_map.xml
new file mode 100644
index 0000000000..ffb955a311
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_jl_bizmap_map.xml
@@ -0,0 +1,14 @@
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_m2_bizmap_map.xml b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_m2_bizmap_map.xml
new file mode 100644
index 0000000000..625b786557
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_m2_bizmap_map.xml
@@ -0,0 +1,14 @@
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_no_data_common_view.xml b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_no_data_common_view.xml
new file mode 100644
index 0000000000..e27a976e9b
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_no_data_common_view.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_no_line_view.xml b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_no_line_view.xml
new file mode 100644
index 0000000000..6d81e77fc7
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_no_line_view.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_stations_common_item.xml b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_stations_common_item.xml
new file mode 100644
index 0000000000..28078230ca
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_stations_common_item.xml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_switch_line.xml b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_switch_line.xml
new file mode 100644
index 0000000000..fcd32f3b8f
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_switch_line.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_switch_line_list_item.xml b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_switch_line_list_item.xml
new file mode 100644
index 0000000000..ec0a05030b
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_switch_line_list_item.xml
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_switch_line_list_task_item.xml b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_switch_line_list_task_item.xml
new file mode 100644
index 0000000000..07cb6d0eec
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_switch_line_list_task_item.xml
@@ -0,0 +1,18 @@
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_tap_position.xml b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_tap_position.xml
new file mode 100644
index 0000000000..0aa49df0bd
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_tap_position.xml
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_test_bar_view.xml b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_test_bar_view.xml
new file mode 100644
index 0000000000..a64bdaa4d9
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_test_bar_view.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_wirte_off_view.xml b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_wirte_off_view.xml
new file mode 100644
index 0000000000..60f94aace3
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/layout/shuttle_wirte_off_view.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/raw/bus_away_passengers.json b/OCH/shuttle_weaknet/driver/src/main/res/raw/bus_away_passengers.json
new file mode 100644
index 0000000000..e76436f2dc
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/raw/bus_away_passengers.json
@@ -0,0 +1,184 @@
+{
+ "code": 0,
+ "msg": "",
+ "detailMsg": "",
+ "result": {
+ "info": [
+ {
+ "_id": "cee57b3ae07c4486b0357319368487d7",
+ "orderNo": "XB20210422000002",
+ "orderType": 10,
+ "userName": "董QAD",
+ "userPhone": "15631204018",
+ "startStationId": 1,
+ "startStation": "万集东门站",
+ "startStationCoordinate": [
+ 116.7354579447,
+ 40.1974932972
+ ],
+ "endStationId": 2,
+ "endStation": "顺密路口站",
+ "endStationCoordinate": [
+ 116.721520973,
+ 40.1940181096
+ ],
+ "orderDispatchType": 7,
+ "carNum": "京NB010",
+ "sn": "F803EB2046PZD00149",
+ "orderStartTime": "2021-04-22 16:31:58",
+ "orderEndTime": "2021-04-26 10:38:13",
+ "arrivedStartStationTime": null,
+ "arrivedEndStationTime": null,
+ "cityCode": "010",
+ "areaCode": "1001",
+ "createTime": "2021-04-22 16:31:58",
+ "updateTime": "2021-04-26 10:38:13",
+ "personNum": 1,
+ "travelDistance": 1.2,
+ "vehicleColour": null,
+ "lastBrandName": null,
+ "headImgUrl": null
+ },
+ {
+ "_id": "ce69b1bcfb9840c6a4563bc6ef947caf",
+ "orderNo": "XB20210426000000",
+ "orderType": 10,
+ "userName": "董QAD",
+ "userPhone": "15631204018",
+ "startStationId": 1,
+ "startStation": "万集东门站",
+ "startStationCoordinate": [
+ 116.7354579447,
+ 40.1974932972
+ ],
+ "endStationId": 2,
+ "endStation": "顺密路口站",
+ "endStationCoordinate": [
+ 116.721520973,
+ 40.1940181096
+ ],
+ "orderDispatchType": 7,
+ "carNum": "京NB010",
+ "sn": "F803EB2046PZD00149",
+ "orderStartTime": "2021-04-26 10:38:48",
+ "orderEndTime": "2021-04-26 10:46:16",
+ "arrivedStartStationTime": null,
+ "arrivedEndStationTime": null,
+ "cityCode": "010",
+ "areaCode": "1001",
+ "createTime": "2021-04-26 10:38:48",
+ "updateTime": "2021-04-26 10:46:16",
+ "personNum": 1,
+ "travelDistance": 1.2,
+ "vehicleColour": null,
+ "lastBrandName": null,
+ "headImgUrl": null
+ },
+ {
+ "_id": "cae07b56f41c4e0fa60ab3543ffc258e",
+ "orderNo": "XB20210426000001",
+ "orderType": 10,
+ "userName": "董QAD",
+ "userPhone": "15631204018",
+ "startStationId": 1,
+ "startStation": "万集东门站",
+ "startStationCoordinate": [
+ 116.7354579447,
+ 40.1974932972
+ ],
+ "endStationId": 2,
+ "endStation": "顺密路口站",
+ "endStationCoordinate": [
+ 116.721520973,
+ 40.1940181096
+ ],
+ "orderDispatchType": 7,
+ "carNum": "京NB010",
+ "sn": "F803EB2046PZD00149",
+ "orderStartTime": "2021-04-26 10:47:05",
+ "orderEndTime": "2021-04-26 10:48:07",
+ "arrivedStartStationTime": null,
+ "arrivedEndStationTime": null,
+ "cityCode": "010",
+ "areaCode": "1001",
+ "createTime": "2021-04-26 10:47:05",
+ "updateTime": "2021-04-26 10:48:07",
+ "personNum": 1,
+ "travelDistance": 1.2,
+ "vehicleColour": null,
+ "lastBrandName": null,
+ "headImgUrl": null
+ },
+ {
+ "_id": "62bc84afbc434d01b644c74ee406e772",
+ "orderNo": "XB20210426000002",
+ "orderType": 10,
+ "userName": "董QAD",
+ "userPhone": "15631204018",
+ "startStationId": 1,
+ "startStation": "万集东门站",
+ "startStationCoordinate": [
+ 116.7354579447,
+ 40.1974932972
+ ],
+ "endStationId": 2,
+ "endStation": "顺密路口站",
+ "endStationCoordinate": [
+ 116.721520973,
+ 40.1940181096
+ ],
+ "orderDispatchType": 7,
+ "carNum": "京NB010",
+ "sn": "F803EB2046PZD00149",
+ "orderStartTime": "2021-04-26 10:48:22",
+ "orderEndTime": "2021-04-26 10:50:32",
+ "arrivedStartStationTime": null,
+ "arrivedEndStationTime": null,
+ "cityCode": "010",
+ "areaCode": "1001",
+ "createTime": "2021-04-26 10:48:22",
+ "updateTime": "2021-04-26 10:50:32",
+ "personNum": 1,
+ "travelDistance": 1.2,
+ "vehicleColour": null,
+ "lastBrandName": null,
+ "headImgUrl": null
+ },
+ {
+ "_id": "fa3214c7a6ec411bb3d6edbc98907423",
+ "orderNo": "XB20210426000009",
+ "orderType": 10,
+ "userName": "董QAD",
+ "userPhone": "15631204018",
+ "startStationId": 1,
+ "startStation": "万集东门站",
+ "startStationCoordinate": [
+ 116.7354579447,
+ 40.1974932972
+ ],
+ "endStationId": 2,
+ "endStation": "顺密路口站",
+ "endStationCoordinate": [
+ 116.721520973,
+ 40.1940181096
+ ],
+ "orderDispatchType": 7,
+ "carNum": "京NB010",
+ "sn": "F803EB2046PZD00149",
+ "orderStartTime": "2021-04-26 19:26:05",
+ "orderEndTime": "2021-04-27 14:35:50",
+ "arrivedStartStationTime": null,
+ "arrivedEndStationTime": null,
+ "cityCode": "010",
+ "areaCode": "1001",
+ "createTime": "2021-04-26 19:26:05",
+ "updateTime": "2021-04-27 14:35:50",
+ "personNum": 1,
+ "travelDistance": 1.2,
+ "vehicleColour": null,
+ "lastBrandName": null,
+ "headImgUrl": null
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/raw/bus_di.mp3 b/OCH/shuttle_weaknet/driver/src/main/res/raw/bus_di.mp3
new file mode 100644
index 0000000000..5f313f8970
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/raw/bus_di.mp3 differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/raw/bus_order_1.json b/OCH/shuttle_weaknet/driver/src/main/res/raw/bus_order_1.json
new file mode 100644
index 0000000000..050b67447d
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/raw/bus_order_1.json
@@ -0,0 +1,28 @@
+{
+ "_id": "62bc84afbc434d01b644c74ee406e772",
+ "areaCode": "1001",
+ "carNum": "京NB010",
+ "cityCode": "010",
+ "createTime": "Apr 26, 2021 10:48:22 AM",
+ "endStation": "顺密路口站",
+ "endStationCoordinate": [
+ 116.721520973,
+ 40.1940181096
+ ],
+ "endStationId": 2,
+ "orderDispatchType": 1,
+ "orderNo": "XB20210426000002",
+ "orderStartTime": "Apr 26, 2021 10:48:22 AM",
+ "orderType": 10,
+ "sn": "F803EB2046PZD00149",
+ "startStation": "万集东门站",
+ "startStationCoordinate": [
+ 116.7354579447,
+ 40.1974932972
+ ],
+ "startStationId": 1,
+ "travelDistance": 1.2,
+ "updateTime": "Apr 26, 2021 10:48:23 AM",
+ "userName": "董QAD",
+ "userPhone": "15631204018"
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/raw/bus_station_list1.json b/OCH/shuttle_weaknet/driver/src/main/res/raw/bus_station_list1.json
new file mode 100644
index 0000000000..c74daa1174
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/raw/bus_station_list1.json
@@ -0,0 +1,69 @@
+{
+ "code": 0,
+ "msg": "",
+ "detailMsg": "",
+ "result": {
+ "site": [
+ {
+ "lineId": 1.0,
+ "siteId": 1.0,
+ "siteName": "万集东门站",
+ "cityCode": "010",
+ "areaCode": "1001",
+ "areaName": "顺义区",
+ "currentLocation": [
+ 116.7354579447,
+ 40.1974932972
+ ],
+ "lon": 116.7354579447,
+ "lat": 40.1974932972,
+ "siteDesc": "万集东门站",
+ "siteState": 1.0,
+ "isCurrentSite": 1.0,
+ "siteColor": 1.0,
+ "peoples": "0",
+ "ifStop": 1.0
+ },
+ {
+ "lineId": 1.0,
+ "siteId": 2.0,
+ "siteName": "市政府前街18号",
+ "cityCode": "010",
+ "areaCode": "1001",
+ "areaName": "顺义区",
+ "currentLocation": [
+ 116.729134342,
+ 40.1953113732
+ ],
+ "lon": 116.729134342,
+ "lat": 40.1953113732,
+ "siteDesc": "市政府前街18号",
+ "siteState": 1.0,
+ "isCurrentSite": 3.0,
+ "siteColor": 2.0,
+ "peoples": "0",
+ "ifStop": 0.0
+ },
+ {
+ "lineId": 1.0,
+ "siteId": 3.0,
+ "siteName": "顺密路口站",
+ "cityCode": "010",
+ "areaCode": "1001",
+ "areaName": "顺义区",
+ "currentLocation": [
+ 116.721520973,
+ 40.1940181096
+ ],
+ "lon": 116.721520973,
+ "lat": 40.1940181096,
+ "siteDesc": "顺密路口站",
+ "siteState": 1.0,
+ "isCurrentSite": 0.0,
+ "siteColor": 0.0,
+ "peoples": "0",
+ "ifStop": 1.0
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/raw/bus_station_list2.json b/OCH/shuttle_weaknet/driver/src/main/res/raw/bus_station_list2.json
new file mode 100644
index 0000000000..48d6782cc3
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/raw/bus_station_list2.json
@@ -0,0 +1,109 @@
+{
+ "code": 0,
+ "msg": "",
+ "detailMsg": "",
+ "result": {
+ "site": [
+ {
+ "lineId": 1.0,
+ "siteId": 1.0,
+ "siteName": "万集东门站",
+ "cityCode": "010",
+ "areaCode": "1001",
+ "areaName": "顺义区",
+ "currentLocation": [
+ 116.7354579447,
+ 40.1974932972
+ ],
+ "lon": 116.7354579447,
+ "lat": 40.1974932972,
+ "siteDesc": "万集东门站",
+ "siteState": 1.0,
+ "isCurrentSite": 0.0,
+ "siteColor": 0.0,
+ "peoples": "0",
+ "ifStop": 1.0
+ },
+ {
+ "lineId": 1.0,
+ "siteId": 1.0,
+ "siteName": "万集东门站",
+ "cityCode": "010",
+ "areaCode": "1001",
+ "areaName": "顺义区",
+ "currentLocation": [
+ 116.7374429112,
+ 40.2023987087
+ ],
+ "lon": 116.7374429112,
+ "lat": 40.2023987087,
+ "siteDesc": "万集东门站",
+ "siteState": 1.0,
+ "isCurrentSite": 0.0,
+ "siteColor": 0.0,
+ "peoples": "0",
+ "ifStop": 1.0
+ },
+ {
+ "lineId": 1.0,
+ "siteId": 2.0,
+ "siteName": "顺密路口站",
+ "cityCode": "010",
+ "areaCode": "1001",
+ "areaName": "顺义区",
+ "currentLocation": [
+ 116.721520973,
+ 40.1940181096
+ ],
+ "lon": 116.721520973,
+ "lat": 40.1940181096,
+ "siteDesc": "顺密路口站",
+ "siteState": 1.0,
+ "isCurrentSite": 1.0,
+ "siteColor": 1.0,
+ "peoples": "0",
+ "ifStop": 1.0
+ },
+ {
+ "lineId": 1.0,
+ "siteId": 2.0,
+ "siteName": "顺密路口站",
+ "cityCode": "010",
+ "areaCode": "1001",
+ "areaName": "顺义区",
+ "currentLocation": [
+ 116.723146,
+ 40.179637
+ ],
+ "lon": 116.723146,
+ "lat": 40.179637,
+ "siteDesc": "顺密路口站",
+ "siteState": 1.0,
+ "isCurrentSite": 1.0,
+ "siteColor": 1.0,
+ "peoples": "0",
+ "ifStop": 1.0
+ },
+ {
+ "lineId": 2.0,
+ "siteId": 2.0,
+ "siteName": "顺密路口站",
+ "cityCode": "010",
+ "areaCode": "1001",
+ "areaName": "顺义区",
+ "currentLocation": [
+ 116.738835502,
+ 40.2023958306
+ ],
+ "lon": 116.738835502,
+ "lat": 40.2023958306,
+ "siteDesc": "顺密路口站",
+ "siteState": 1.0,
+ "isCurrentSite": 1.0,
+ "siteColor": 1.0,
+ "peoples": "0",
+ "ifStop": 1.0
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/raw/end_marker.nt3d b/OCH/shuttle_weaknet/driver/src/main/res/raw/end_marker.nt3d
new file mode 100644
index 0000000000..4d4f356f0b
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/raw/end_marker.nt3d differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/raw/star_marker.nt3d b/OCH/shuttle_weaknet/driver/src/main/res/raw/star_marker.nt3d
new file mode 100644
index 0000000000..94440d9eb6
Binary files /dev/null and b/OCH/shuttle_weaknet/driver/src/main/res/raw/star_marker.nt3d differ
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/values/attrs.xml b/OCH/shuttle_weaknet/driver/src/main/res/values/attrs.xml
new file mode 100644
index 0000000000..396db92f74
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/values/attrs.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/values/colors.xml b/OCH/shuttle_weaknet/driver/src/main/res/values/colors.xml
new file mode 100644
index 0000000000..90c817402c
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/values/colors.xml
@@ -0,0 +1,63 @@
+
+
+ #FF1FA7FF
+ #FFFFFFFF
+ #FFFFFFFF
+ #FF51649D
+ #7F8299EB
+
+ #51649D
+ #427d8e
+ #1FA7FF
+ #3FC281
+ #427d8e
+ #3FC281
+
+ #FFFFFF
+ #99FFFFFF
+ #FF52BBFF
+
+ #BF30334C
+ #fff
+ #f1f1f1
+
+ #7DE261
+ #FF2B2B
+ #E3BC59
+ #FFF
+ #256BFF
+ #FFFFFF
+
+ #DB3137
+ #3E77F6
+ #323C6F
+
+ #2966EC
+ #F7151D41
+
+ #19FFFFFF
+ #FFFFFF
+
+ #FFFFA28B
+ #FFDA1100
+ #FF60FFD3
+ #FF006D43
+ #FFFFE198
+ #FFFF9B00
+ #59FFFFFF
+
+ #CCB9C3E9
+ #4Dffffff
+
+ #8E9DD4
+ #2B6EFF
+ #00FFF8
+
+ #FFFFFF
+ #4DFFFFFF
+ #FFFFFF
+ #323C6F
+ #CAD6FF
+ #BF0E3DBC
+ #BF1E2E89
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/values/dimens.xml b/OCH/shuttle_weaknet/driver/src/main/res/values/dimens.xml
new file mode 100644
index 0000000000..fd1ec0cd92
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/values/dimens.xml
@@ -0,0 +1,165 @@
+
+
+
+ 460dp
+ 30dp
+
+ 110dp
+ 40dp
+ 320dp
+ 20dp
+ 40dp
+ 320dp
+ 460dp
+ 70dp
+ 460dp
+ 130dp
+ 30dp
+
+ #FFFFFF
+ #4DFFFFFF
+ #FFFFFF
+ #323C6F
+ 10dp
+ 20dp
+ 200dp
+ 52dp
+ 65dp
+ 20dp
+ 50dp
+ 20dp
+ 38dp
+ 33dp
+ 368dp
+ 76dp
+ 60dp
+ 276dp
+ 112dp
+ 22dp
+ 36dp
+ 50dp
+ 822dp
+
+ 46dp
+ 700dp
+ 120dp
+ 560dp
+ 116dp
+ 50dp
+
+ 225dp
+ 154dp
+ 60dp
+ 40dp
+ 23dp
+ 210dp
+ 120dp
+ 15dp
+ 17dp
+ 154dp
+ 130dp
+ 60dp
+
+ 27dp
+
+
+ 40dp
+ 32dp
+ 13dp
+ 12dp
+ 350dp
+
+ 30dp
+ 618dp
+ 754dp
+
+ 92dp
+
+ 112dp
+ 112dp
+
+
+
+
+
+ 300dp
+ 348dp
+ 211dp
+ 276dp
+
+
+ 220dp
+ 98dp
+ 159dp
+
+ 32dp
+ 20dp
+ 40dp
+ 42dp
+
+ 15dp
+
+ 20dp
+ 36dp
+ 28dp
+ 36dp
+
+ 3dp
+ 3dp
+ 17dp
+ 17dp
+
+
+ 300dp
+ 270dp
+ 30dp
+ 24dp
+ 24dp
+ 1dp
+ 30dp
+ 23dp
+ 30dp
+ 146dp
+ 20dp
+ 23dp
+ 30dp
+ 23dp
+ 26dp
+ 34dp
+ 20dp
+ 80dp
+ 3dp
+ 34dp
+ 20dp
+ 28dp
+ 27dp
+
+
+ 25.6dp
+ 20dp
+ 20dp
+ 64dp
+ 16dp
+
+ 40dp
+ 40dp
+ 46dp
+ 24dp
+
+ 530dp
+ 492dp
+
+ 20dp
+ 20dp
+ 70dp
+ 130dp
+ 93dp
+ 150dp
+ 70dp
+
+ 24dp
+ 616dp
+ 180dp
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/values/strings.xml b/OCH/shuttle_weaknet/driver/src/main/res/values/strings.xml
new file mode 100644
index 0000000000..7558acbeec
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/values/strings.xml
@@ -0,0 +1,66 @@
+
+ 近距视角
+ 远距视角
+ 启动中…
+ 启动成功
+ 启动失败
+ 自动驾驶
+ 任务列表
+ 暂无任务
+ 选择时间
+ 路线:
+ 起点:
+ 终点:
+ 确认
+ 选择任务
+ 结束任务
+ 自动驾驶状态中,不可切换或结束路线
+ 当前行程未完成,不可切换路线
+ 当前车辆无路线\n请联系运营人员绑定
+ 起点:
+ 终点:
+ 往%1$s方向
+ 更换任务成功
+ 更换任务失败
+
+ 起点:
+ 终点:
+ 当前站点:
+ 下一站:
+ 自动驾驶状态为0不可用
+ 进站
+ 起
+ 终
+ 班次:
+
+ 提示
+ 您确认要结束任务吗?
+ 确认
+ 取消
+
+ 暂无任务
+ 本站核销成功:%1$d人
+ 本站核销成功:0人
+
+
+
+ 距离发车时间还有%1$s分钟
+
+ 平行驾驶
+
+
+
+ 已到达%1$s,带好随身物品,下车请注意安全。
+ We are arriving at %1$s ,get off with your belongings
+ %1$s 역에 도착했습니다 , 소지품 챙겨서 내리세요
+
+ 车辆起步,请扶稳坐好,前方到站是%1$s,请下车的乘客做好准备。
+ The next station is %1$s ,please get ready for your arrival
+ 전방에서 역에 도착하는 %1$s ,차에서 내리는 승객은 준비하세요
+
+ 感谢您体验\'蘑菇车联\'自动驾驶小巴车,我们下次再见。
+ Thank you for experiencing the self-driving minibus. See you next time
+ 자율주행 버스를 체험해 주셔서 감사합니다. 다음에 또 뵙겠습니다
+
+
+
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/values/style.xml b/OCH/shuttle_weaknet/driver/src/main/res/values/style.xml
new file mode 100644
index 0000000000..36d7ef0d93
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/values/style.xml
@@ -0,0 +1,23 @@
+
+
+
+
diff --git a/OCH/shuttle_weaknet/driver/src/main/res/xml/bus_switch_line_list_item_scene.xml b/OCH/shuttle_weaknet/driver/src/main/res/xml/bus_switch_line_list_item_scene.xml
new file mode 100644
index 0000000000..587a6eccbe
--- /dev/null
+++ b/OCH/shuttle_weaknet/driver/src/main/res/xml/bus_switch_line_list_item_scene.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/.gitignore b/OCH/shuttle_weaknet/passenger/.gitignore
new file mode 100644
index 0000000000..42afabfd2a
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/README.md b/OCH/shuttle_weaknet/passenger/README.md
new file mode 100644
index 0000000000..6175119b78
--- /dev/null
+++ b/OCH/shuttle_weaknet/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/shuttle_weaknet/passenger/build.gradle b/OCH/shuttle_weaknet/passenger/build.gradle
new file mode 100644
index 0000000000..cddf5c35e9
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/build.gradle
@@ -0,0 +1,85 @@
+apply plugin: 'com.android.library'
+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", "shuttle"+project.getName())
+ }
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ lintOptions {
+ abortOnError false
+ }
+
+ 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'
+ }
+ }
+
+ sourceSets {
+ main {
+ res.srcDirs = [
+ 'src/main/res',
+ 'src/main/res/m2',
+ 'src/main/res/jinlv',
+ ]
+ java.srcDirs = [
+ 'src/main/java',
+ 'src/main/java/m2',
+ 'src/main/java/jinlv',
+ ]
+ }
+ }
+}
+
+dependencies {
+ implementation fileTree(dir: "libs", include: ["*.jar"])
+ implementation rootProject.ext.dependencies.kotlinstdlib
+ 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 rootProject.ext.dependencies.serialport
+ implementation project(":OCH:common:common")
+ compileOnly project(":libraries:mogo-map")
+ implementation project(':core:mogo-core-res')
+
+ androidTestImplementation rootProject.ext.dependencies.androidxjunit
+ testImplementation rootProject.ext.dependencies.junit
+
+}
+
+apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/consumer-rules.pro b/OCH/shuttle_weaknet/passenger/consumer-rules.pro
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/OCH/shuttle_weaknet/passenger/gradle.properties b/OCH/shuttle_weaknet/passenger/gradle.properties
new file mode 100644
index 0000000000..2ed1ed2f42
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/gradle.properties
@@ -0,0 +1,3 @@
+GROUP=com.mogo.och
+POM_ARTIFACT_ID=och-bus-passenger
+VERSION_CODE=1
diff --git a/OCH/shuttle_weaknet/passenger/proguard-rules.pro b/OCH/shuttle_weaknet/passenger/proguard-rules.pro
new file mode 100644
index 0000000000..481bb43481
--- /dev/null
+++ b/OCH/shuttle_weaknet/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/shuttle_weaknet/passenger/src/androidTest/java/passenger/ExampleInstrumentedTest.java b/OCH/shuttle_weaknet/passenger/src/androidTest/java/passenger/ExampleInstrumentedTest.java
new file mode 100644
index 0000000000..2685ade0a4
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/androidTest/java/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/shuttle_weaknet/passenger/src/main/AndroidManifest.xml b/OCH/shuttle_weaknet/passenger/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..549784ca83
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/AndroidManifest.xml
@@ -0,0 +1,5 @@
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/assets/m2_map_style.data b/OCH/shuttle_weaknet/passenger/src/main/assets/m2_map_style.data
new file mode 100755
index 0000000000..77da1f0284
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/assets/m2_map_style.data differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/assets/m2_map_style_extra.data b/OCH/shuttle_weaknet/passenger/src/main/assets/m2_map_style_extra.data
new file mode 100755
index 0000000000..6b25c39519
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/assets/m2_map_style_extra.data differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/assets/map_style.data b/OCH/shuttle_weaknet/passenger/src/main/assets/map_style.data
new file mode 100644
index 0000000000..085e06a2db
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/assets/map_style.data differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/assets/map_style_extra.data b/OCH/shuttle_weaknet/passenger/src/main/assets/map_style_extra.data
new file mode 100644
index 0000000000..892eda73f9
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/assets/map_style_extra.data differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/ShuttlePassengerProvider.kt b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/ShuttlePassengerProvider.kt
new file mode 100644
index 0000000000..3fbe34328f
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/ShuttlePassengerProvider.kt
@@ -0,0 +1,70 @@
+package com.mogo.och.shuttle.passenger
+
+import android.content.Context
+import android.view.View
+import androidx.fragment.app.Fragment
+import com.alibaba.android.arouter.facade.annotation.Route
+import com.mogo.eagle.core.data.config.FunctionBuildConfig
+import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
+import com.mogo.eagle.core.utilcode.util.ActivityUtils
+import com.mogo.eagle.core.utilcode.util.DeviceUtils
+import com.mogo.eagle.core.utilcode.util.MultiDisplayUtils
+import com.mogo.och.common.module.constant.OchCommonConst
+import com.mogo.och.common.module.biz.provider.CommonServiceImpl
+import com.mogo.och.common.module.wigets.media.MediaPlayerActivity
+import com.mogo.och.shuttle.passenger.model.TicketModel
+import com.mogo.och.shuttle.passenger.ui.BusPStatusBarView
+import com.mogo.och.shuttle.passenger.ui.BusPassengerRouteFragment
+import com.mogo.och.shuttle.passenger.ui.PM2BaseFragment
+import com.mogo.och.shuttle.passenger.ui.widget.M2StatusBarView
+
+/**
+ * 网约车-Bus-乘客端
+ *
+ * Created on 2022/3/29
+ */
+@Route(path = OchCommonConst.SHUTTLE_PASSENGER)
+class ShuttlePassengerProvider : CommonServiceImpl() {
+
+ private val tag = ShuttlePassengerProvider::class.java.simpleName
+ private var mPM2Fragment: Fragment?=null
+
+ override fun init(context: Context) {
+ TicketModel.load()
+ }
+
+ override fun getStatusBarView(context: Context): View {
+ if(statusBarView==null){
+ statusBarView = if (AppIdentityModeUtils.isB2(FunctionBuildConfig.appIdentityMode)) {
+ M2StatusBarView(context);
+ } else if (AppIdentityModeUtils.isB1(FunctionBuildConfig.appIdentityMode)) {
+ BusPStatusBarView(context);
+ }else{
+ BusPStatusBarView(context);
+ }
+ }
+ return statusBarView!!
+ }
+
+ override fun getFragment(): Fragment {
+ if (AppIdentityModeUtils.isB1(FunctionBuildConfig.appIdentityMode) && DeviceUtils.isEB5Model()) {
+ MultiDisplayUtils.startActWithSecond(ActivityUtils.getTopActivity(), MediaPlayerActivity::class.java)
+ }
+ if(mPM2Fragment==null){
+ mPM2Fragment = if (AppIdentityModeUtils.isB2(FunctionBuildConfig.appIdentityMode)) {
+ PM2BaseFragment()
+ }else if (AppIdentityModeUtils.isB1(FunctionBuildConfig.appIdentityMode)) {
+ BusPassengerRouteFragment()
+ }else{
+ BusPassengerRouteFragment()
+ }
+ }
+ return mPM2Fragment!!
+ }
+
+ override fun resetFragment() {
+ super.resetFragment()
+ mPM2Fragment = null
+ }
+
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/bean/request/PassengerQueryLineRequest.java b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/bean/request/PassengerQueryLineRequest.java
new file mode 100644
index 0000000000..48c312b288
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/bean/request/PassengerQueryLineRequest.java
@@ -0,0 +1,16 @@
+package com.mogo.och.shuttle.passenger.bean.request;
+
+public
+/**
+ * @author congtaowang
+ * @since 2021/3/22
+ *
+ * 根据车机行驶线路站点信息
+ */
+class PassengerQueryLineRequest {
+
+ private String sn;
+ public PassengerQueryLineRequest(String sn) {
+ this.sn = sn;
+ }
+}
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/bean/request/PassengerWriteOffRequest.java b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/bean/request/PassengerWriteOffRequest.java
new file mode 100644
index 0000000000..1ff5c160a6
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/bean/request/PassengerWriteOffRequest.java
@@ -0,0 +1,50 @@
+package com.mogo.och.shuttle.passenger.bean.request;
+
+public
+/**
+ * @author congtaowang
+ * @since 2021/3/22
+ *
+ * 根据车机行驶线路站点信息
+ */
+class PassengerWriteOffRequest {
+
+ private String sn;
+ private String orderNo;
+ private String uid;
+
+ public PassengerWriteOffRequest(String orderNo, String uid) {
+ this.orderNo = orderNo;
+ this.uid = uid;
+ }
+
+ public PassengerWriteOffRequest(String sn, String orderNo, String uid) {
+ this.sn = sn;
+ this.orderNo = orderNo;
+ this.uid = uid;
+ }
+
+ public String getSn() {
+ return sn;
+ }
+
+ public void setSn(String sn) {
+ this.sn = sn;
+ }
+
+ public String getOrderNo() {
+ return orderNo;
+ }
+
+ public void setOrderNo(String orderNo) {
+ this.orderNo = orderNo;
+ }
+
+ public String getUid() {
+ return uid;
+ }
+
+ public void setUid(String uid) {
+ this.uid = uid;
+ }
+}
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/bean/response/PassengerOperationStatusResponse.java b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/bean/response/PassengerOperationStatusResponse.java
new file mode 100644
index 0000000000..b6781937bb
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/bean/response/PassengerOperationStatusResponse.java
@@ -0,0 +1,21 @@
+package com.mogo.och.shuttle.passenger.bean.response;
+
+import com.mogo.eagle.core.data.BaseData;
+
+/**
+ * @author congtaowang
+ * @since 2021/3/22
+ *
+ * 小巴车运营状态返回参数
+ */
+public class PassengerOperationStatusResponse 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/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/bean/response/PassengerRoutesResponse.java b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/bean/response/PassengerRoutesResponse.java
new file mode 100644
index 0000000000..3b9fbe3ec1
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/bean/response/PassengerRoutesResponse.java
@@ -0,0 +1,29 @@
+package com.mogo.och.shuttle.passenger.bean.response;
+
+import com.mogo.eagle.core.data.BaseData;
+import com.mogo.och.data.bean.BusRoutesResult;
+
+/**
+ * 网约车小巴路线接口请求响应结果 返回的是对应司机屏的线路信息
+ *
+ * @author tongchenfei
+ */
+public class PassengerRoutesResponse extends BaseData {
+ private BusRoutesResult data;
+
+ public BusRoutesResult getResult() {
+ return data;
+ }
+
+ public void setResult(BusRoutesResult data) {
+ this.data = data;
+ }
+
+ @Override
+ public String toString() {
+ return "OchBusRoutesResponse{" +
+ "data=" + data +
+ '}';
+ }
+
+}
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/bean/response/PassengerWriteOffResponse.kt b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/bean/response/PassengerWriteOffResponse.kt
new file mode 100644
index 0000000000..d46146c23c
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/bean/response/PassengerWriteOffResponse.kt
@@ -0,0 +1,13 @@
+package com.mogo.och.shuttle.passenger.bean.response
+
+import com.mogo.eagle.core.data.BaseData
+
+
+data class PassengerWriteOffResponse(val data: Result?) : BaseData(){
+ data class Result(
+ val phone: String?,
+ val ticketSize: Int?,
+ val ticketName: String?,
+ val remainingTimes: Long?
+ )
+}
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/constant/BusPassengerConst.kt b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/constant/BusPassengerConst.kt
new file mode 100644
index 0000000000..82b5f1ef09
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/constant/BusPassengerConst.kt
@@ -0,0 +1,35 @@
+package com.mogo.och.shuttle.passenger.constant
+
+/**
+ * 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 = 10
+ //接驳/B2平均速度 bus的平均里程:10km/h
+ const val SHUTTLE_AVERAGE_SPEED = 10
+
+ const val QUERY_BUS_P_STATION_DELAY = 3 * 1000L
+
+ const val ARRIVE_DISTANCE_4_STATION_INTRODUCE = 200 //站点介绍
+ }
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/manager/scnner/ScannerChainLogManager.kt b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/manager/scnner/ScannerChainLogManager.kt
new file mode 100644
index 0000000000..abc506434e
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/manager/scnner/ScannerChainLogManager.kt
@@ -0,0 +1,49 @@
+package com.mogo.och.shuttle.passenger.manager.scnner
+
+import android.text.TextUtils
+import com.mogo.commons.debug.DebugConfig
+import com.mogo.commons.storage.SharedPrefsMgr
+import com.mogo.commons.utils.MogoAnalyticUtils
+import com.mogo.eagle.core.data.app.AppConfigInfo
+import com.mogo.eagle.core.data.deva.chain.ChainConstant
+import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d
+import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
+import com.mogo.eagle.core.utilcode.util.DateTimeUtils
+import com.zhjt.service.chain.ChainLog
+
+object ScannerChainLogManager {
+
+ private val TAG = ScannerChainLogManager::class.java.simpleName
+
+ const val EVENT_KEY_INFE_WITH_CHANGE = "event_key_och_scanner_info"
+
+ /**
+ * @param Info 事件
+ * @param changeInfo 数据
+ */
+ @ChainLog(
+ linkChainLog = ChainConstant.CHAIN_TYPE_OCH,
+ linkCode = ChainConstant.CHAIN_SOURCE_OCH,
+ nodeAliasCode = ChainConstant.CHAIN_CODE_OCH_COMMON_DISTANCE,
+ paramIndexes = [0,1]
+ )
+ @JvmStatic
+ fun writeChainLog(info: String, changeInfo: String,upload:Boolean = true,eventID:String=EVENT_KEY_INFE_WITH_CHANGE) {
+ try {
+ d(SceneConstant.M_OCHCOMMON + TAG, info+changeInfo)
+ if(upload) {
+ val plateNum = AppConfigInfo.plateNumber
+ val params = HashMap()
+ params["sn"] = SharedPrefsMgr.getInstance().sn
+ params["env"] = DebugConfig.getNetMode()
+ params["plate_number"] = if (TextUtils.isEmpty(plateNum)) "" else plateNum
+ params["time"] = DateTimeUtils.getTimeText(DateTimeUtils.yyyy_MM_dd_HH_mm_ss)
+ params[info] = changeInfo
+ MogoAnalyticUtils.track(eventID, params)
+ }
+ }catch (e:Exception){
+ e.printStackTrace()
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/manager/scnner/ScannerManager.kt b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/manager/scnner/ScannerManager.kt
new file mode 100644
index 0000000000..a5e19b5757
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/manager/scnner/ScannerManager.kt
@@ -0,0 +1,257 @@
+package com.mogo.och.shuttle.passenger.manager.scnner
+
+import android.net.Uri
+import com.mogo.commons.AbsMogoApplication
+import com.mogo.eagle.core.function.api.telematic.IReceivedMsgListener
+import com.mogo.eagle.core.function.call.telematic.CallerTelematicListenerManager
+import com.mogo.eagle.core.function.call.telematic.CallerTelematicManager
+import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
+import com.mogo.eagle.core.utilcode.mogo.logger.Logger
+import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
+import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_BUS_P
+import com.mogo.eagle.core.utilcode.util.GsonUtils
+import com.mogo.eagle.core.utilcode.util.StringUtils
+import com.mogo.och.common.module.manager.socket.lan.bean.WriteOffDevicesMsg
+import com.mogo.och.common.module.manager.socket.lan.bean.WriteOffMsg
+import com.mogo.och.common.module.constant.OchCommonConst
+import com.mogo.och.common.module.manager.socket.lan.LanSocketManager
+import com.mogo.support.serialport.client.SerialPortManager
+import com.mogo.support.serialport.client.SerialPortManager.SERVICE_STATE
+import com.mogo.support.serialport.client.listener.OnDeviceVerificationListener
+import com.mogo.support.serialport.client.listener.OnSerialPortListener
+import com.mogo.support.serialport.common.verification.UnpackStatus
+import com.mogo.support.serialport.common.verification.data.VerificationActiveData
+import java.util.concurrent.ConcurrentHashMap
+import kotlin.properties.Delegates
+
+
+object ScannerManager : OnSerialPortListener, OnDeviceVerificationListener(), IReceivedMsgListener {
+
+ private val TAG = "ScannerManager"
+
+ private var serialPortManager = SerialPortManager()
+
+ private val stateChanageListeners: ConcurrentHashMap =
+ ConcurrentHashMap()
+
+ private var driverSn:String by Delegates.observable("") { _, oldV, newV ->
+ if (oldV != newV) {
+ // sn 发生了改变 需要向司机屏推送当前链接的状态
+ sendScannerState()
+ }
+ }
+
+ private var bindStatus: BindStatus by Delegates.observable(BindStatus.NOTHING) { _, oldV, newV ->
+ if (oldV != newV) {
+ try {
+ CallerLogger.d(SceneConstant.M_OCHCOMMON + TAG, "状态发生变化old:${oldV}_new:${newV}")
+ if(newV!=BindStatus.BIND_SUCCEED) {
+ dispatchMsg(newV)
+ }
+ if (stateChanageListeners.size > 0) {
+ stateChanageListeners.forEach {
+ it.value.stateChange(newV, openStatus)
+ }
+ }
+ } catch (e: Exception) {
+ CallerLogger.e(SceneConstant.M_OCHCOMMON + TAG, "扫码枪bind错误")
+ }
+ }
+ }
+
+ private var openStatus: OpenStatus by Delegates.observable(OpenStatus.Unopen) { _, oldV, newV ->
+ if (oldV != newV) {
+ try {
+ if (stateChanageListeners.size > 0) {
+ stateChanageListeners.forEach {
+ it.value.stateChange(bindStatus, newV)
+ }
+ }
+ } catch (e: Exception) {
+ CallerLogger.e(SceneConstant.M_OCHCOMMON + TAG, "扫码枪open错误")
+ }
+ }
+ }
+
+ init {
+ //监听司机端消息
+ CallerTelematicListenerManager.addListener(TAG, this)
+ }
+
+ fun addStateChangeListener(tag: String, listener: StateChangeListener) {
+ if (stateChanageListeners.containsKey(tag)) {
+ return
+ }
+ stateChanageListeners[tag] = listener
+ }
+
+ fun bindService() {
+ serialPortManager.bindService(AbsMogoApplication.getApp(), this)//绑定服务
+ }
+
+ override fun onServiceState(serviceState: Int) {
+ ScannerChainLogManager.writeChainLog(TAG+"bindStatus","绑定服务结果:serviceState:${serviceState}")
+ when (serviceState) {
+ SERVICE_STATE.BIND_SUCCEED -> {
+ CallerLogger.d(M_BUS_P + TAG, "服务绑定成功")
+ bindStatus = BindStatus.BIND_SUCCEED
+ serialPortManager.openVerificationDevice(this)
+ }
+ SERVICE_STATE.BIND_FAILURE_UNINSTALLED -> {
+ CallerLogger.d(M_BUS_P + TAG, "服务绑定失败:未安装串口服务端APP")
+ bindStatus = BindStatus.BIND_FAILURE_UNINSTALLED
+ }
+ SERVICE_STATE.BIND_FAILURE_NO_PERMISSION_NOT_FOUND -> {
+ CallerLogger.d(M_BUS_P + TAG, "服务绑定失败:没有绑定权限或找不到服务(如果是此状态,基本上安装后就可以找到,主要就是权限问题)")
+ bindStatus = BindStatus.BIND_FAILURE_NO_PERMISSION_NOT_FOUND
+ }
+ SERVICE_STATE.EXCEPTION -> {
+ CallerLogger.d(M_BUS_P + TAG, "服务被异常销毁")
+ bindStatus = BindStatus.EXCEPTION
+ }
+ else -> {}
+ }
+ }
+
+ // 查询串口
+ override fun onFindSerialPort(paths: Array?) {
+ CallerLogger.d(M_BUS_P + TAG, "$paths")
+ ScannerChainLogManager.writeChainLog(TAG+"onFindSerialPort","查询串口:${paths}")
+ if(paths==null) {
+ bindStatus = BindStatus.BIND_FAILURE_NO_PERMISSION_NOT_FOUND
+ }
+ }
+
+ override fun onSerialPortState(
+ path: String?,
+ isOpen: Boolean,
+ throwableMessage: String?
+ ) {
+ CallerLogger.d(
+ M_BUS_P + TAG,
+ "path ${path}---isOpen${isOpen}--throwableMessage${throwableMessage}"
+ )
+ ScannerChainLogManager.writeChainLog(TAG+"onSerialPortState","扫码枪是否打开:path${path}_isOpen${isOpen}_throwableMessage${throwableMessage}")
+ openStatus = if (isOpen) {
+ sendMessage2Driver(true,"扫码枪打开成功")
+ OpenStatus.Open
+ } else {
+ sendMessage2Driver(false,"扫码枪打开错误:${throwableMessage}_${path}")
+ OpenStatus.Unopen
+ }
+ }
+
+ override fun onActiveDataReceive(data: VerificationActiveData?) {
+ ScannerChainLogManager.writeChainLog(TAG+"onActiveDataReceive","扫码结果:data:${data}")
+ data?.let {
+ if(data.unpackStatus==UnpackStatus.SUCCEED){
+ "数据类型${it.dataType.name}"
+ CallerLogger.d(M_BUS_P + TAG, "data $it")
+ if(!StringUtils.isEmpty(it.payload)){
+ parseParams(it.payload)
+ }else{
+ CallerLogger.d(M_BUS_P + TAG, "数据错误")
+ sendMessage2DriverWriteOffInfo("扫码数据为空")
+ }
+ }else{
+ sendMessage2DriverWriteOffInfo("解包失败")
+ CallerLogger.d(M_BUS_P + TAG, "解包失败")
+ }
+ }
+ }
+
+ private fun parseParams(payload: String?) {
+ val parse = Uri.parse("${OchCommonConst.getShuttleUrl()}?${payload}")
+ val queryParameterNames = parse.queryParameterNames
+ val mutableMapOf = mutableMapOf()
+ queryParameterNames.forEach {
+ val queryParameter = parse.getQueryParameter(it)
+ if(it!=null&&queryParameter!=null){
+ mutableMapOf[it] = queryParameter
+ }
+ }
+ if(mutableMapOf.isNotEmpty()){
+ if (stateChanageListeners.size > 0) {
+ stateChanageListeners.forEach {
+ it.value.parseData(mutableMapOf,payload)
+ }
+ }
+ }else{
+ sendMessage2DriverWriteOffInfo("扫码参数数据为空:${payload}")
+ }
+
+ }
+
+ /**
+ * @param isConnectScanner 是否打开设备
+ */
+ private fun sendMessage2Driver(isConnectScanner:Boolean,message:String){
+ val msg = WriteOffDevicesMsg(isConnectScanner, message)
+ CallerLogger.d(M_BUS_P + TAG, "sendTaskDetailsToClients = " + GsonUtils.toJson(msg))
+ if(driverSn.isNotEmpty()) {
+ LanSocketManager.sendMsgToServer(msg)
+ }
+ }
+
+ /**
+ * 打开设备后数据异常
+ */
+ private fun sendMessage2DriverWriteOffInfo(message:String){
+ val msg = WriteOffMsg(false, "", 0, "", message,"")
+ CallerLogger.d(M_BUS_P + TAG, "sendTaskDetailsToClients = " + GsonUtils.toJson(msg))
+ LanSocketManager.sendMsgToServer(msg)
+ }
+
+ override fun onReceivedMsg(type: Int, byteArray: ByteArray) {
+
+ }
+
+ override fun onReceivedServerSn(sn: String?) {
+ Logger.d(M_BUS_P + TAG, "司机屏sn:$sn")
+ driverSn = sn?:""
+ }
+
+ /**
+ * 链接司机屏后向司机屏同步扫码枪状态
+ */
+ private fun sendScannerState() {
+ if(bindStatus==BindStatus.BIND_SUCCEED&& openStatus==OpenStatus.Open){
+ sendMessage2Driver(true,"扫码枪打开状态")
+ }else{
+ if(bindStatus==BindStatus.BIND_SUCCEED&& openStatus==OpenStatus.Unopen){
+ sendMessage2Driver(false,"绑定成功、打开失败")
+ }else{
+ dispatchMsg(bindStatus)
+ }
+ }
+ }
+
+ private fun dispatchMsg(newV: BindStatus) {
+ when (newV) {
+ BindStatus.BIND_FAILURE_UNINSTALLED -> {
+ // 服务绑定失败:未安装串口服务端APP
+ sendMessage2Driver(false,"服务绑定失败:未安装串口服务端APP")
+ }
+ BindStatus.BIND_FAILURE_NO_PERMISSION_NOT_FOUND -> {
+ // 服务绑定失败:没有绑定权限或找不到服务(如果是此状态,基本上安装后就可以找到,主要就是权限问题)
+ sendMessage2Driver(false,"服务绑定失败:没有绑定权限或找不到服务")
+ }
+ BindStatus.EXCEPTION -> {
+ // 扫码枪open错误
+ sendMessage2Driver(false,"扫码枪打开错误")
+ }
+ BindStatus.NOTHING -> {}
+ else -> {}
+ }
+ }
+
+
+}
+
+enum class BindStatus {
+ BIND_SUCCEED, BIND_FAILURE_UNINSTALLED ,BIND_FAILURE_NO_PERMISSION_NOT_FOUND,EXCEPTION,NOTHING
+}
+
+enum class OpenStatus {
+ Open, Unopen
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/manager/scnner/ScannerStateView.kt b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/manager/scnner/ScannerStateView.kt
new file mode 100644
index 0000000000..f7b335c3a2
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/manager/scnner/ScannerStateView.kt
@@ -0,0 +1,38 @@
+package com.mogo.och.shuttle.passenger.manager.scnner
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.View
+import androidx.appcompat.widget.AppCompatImageView
+import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
+import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
+import com.mogo.och.common.module.R
+
+class ScannerStateView @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0
+) : AppCompatImageView(context, attrs, defStyleAttr), StateChangeListener {
+ private val TAG = "ScannerStateView"
+
+ init {
+ setImageResource(R.drawable.driver_connect_statis)
+ ScannerManager.addStateChangeListener(TAG,this)
+ }
+
+ override fun stateChange(newBindValue: BindStatus, newOpentValue: OpenStatus) {
+ CallerLogger.d(SceneConstant.M_BUS_P + TAG, "newBindValue = $newBindValue newOpentValue = $newOpentValue")
+ when (newOpentValue) {
+ OpenStatus.Open -> {
+ //成功打开
+ visibility = View.GONE
+ }
+ OpenStatus.Unopen -> {
+ // 打开失败
+ setImageResource(R.drawable.driver_connect_statis)
+ }
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/manager/scnner/StateChangeListener.kt b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/manager/scnner/StateChangeListener.kt
new file mode 100644
index 0000000000..12698fa45e
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/manager/scnner/StateChangeListener.kt
@@ -0,0 +1,6 @@
+package com.mogo.och.shuttle.passenger.manager.scnner
+
+interface StateChangeListener {
+ fun stateChange(newBindValue:BindStatus,newOpentValue:OpenStatus){}
+ fun parseData(params: MutableMap, payload: String?){}
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/model/TicketModel.kt b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/model/TicketModel.kt
new file mode 100644
index 0000000000..e6fa3753ef
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/model/TicketModel.kt
@@ -0,0 +1,103 @@
+package com.mogo.och.shuttle.passenger.model
+
+import com.mogo.commons.AbsMogoApplication
+import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
+import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_BUS_P
+import com.mogo.eagle.core.utilcode.util.GsonUtils
+import com.mogo.och.common.module.manager.socket.lan.bean.WriteOffMsg
+import com.mogo.och.common.module.manager.socket.lan.LanSocketManager
+import com.mogo.och.common.module.network.OchCommonServiceCallback
+import com.mogo.och.shuttle.passenger.bean.request.PassengerWriteOffRequest
+import com.mogo.och.shuttle.passenger.bean.response.PassengerWriteOffResponse
+import com.mogo.och.shuttle.passenger.manager.scnner.ScannerChainLogManager
+import com.mogo.och.shuttle.passenger.manager.scnner.ScannerManager
+import com.mogo.och.shuttle.passenger.manager.scnner.StateChangeListener
+import com.mogo.och.shuttle.passenger.network.PassengerServiceManager
+
+object TicketModel : StateChangeListener {
+
+ private const val TAG = "TicketModel"
+
+ init {
+ ScannerManager.bindService()
+ ScannerManager.addStateChangeListener(TAG, this)
+ }
+
+ fun load(){
+
+ }
+
+ override fun parseData(params: MutableMap, payload: String?) {
+ val orderNo = params["orderNo"]
+ val uid = params["uid"]
+ if(orderNo is String && uid is String){
+ writeOffTicket(orderNo,uid)
+ }else{
+ // 通知司机屏二维码错误
+ sendMessage2Driver("参数错误:${payload}")
+ }
+ }
+
+ private fun writeOffTicket(orderNo: String, uid: String) {
+ val passengerWriteOffRequest = PassengerWriteOffRequest(orderNo, uid)
+ PassengerServiceManager.writeOffTicket(AbsMogoApplication.getApp(),
+ passengerWriteOffRequest,
+ object : OchCommonServiceCallback {
+ override fun onSuccess(data: PassengerWriteOffResponse?) {
+ if (data?.data == null) return
+ val ticketInfo =
+ "核销成功:票种名称:${data.data.ticketName},车票数量:${data.data.ticketSize},预留手机号:${data.data.phone},时间:${data.data.remainingTimes}"
+ CallerLogger.d(M_BUS_P + TAG, ticketInfo)
+ sendMessage2DriverSuccess(data.data,orderNo)
+ }
+
+ override fun onFail(code: Int, msg: String?) {
+ CallerLogger.d(M_BUS_P + TAG, "核销失败 ${code}-----${msg}")
+ when (code) {
+ 6002 -> {sendMessage2Driver("同一订单核销间隔时间需大于2分钟")}
+ 1009 -> {sendMessage2Driver("车票所选乘车日期非今日")}
+ 1005 -> {sendMessage2Driver("车辆未登录、或没有任务")}
+ 1006 -> {sendMessage2Driver("车票路线信息与当前车辆执行任务的路线信息不符合")}
+ 1008 -> {sendMessage2Driver("车票剩余可用次数为0")}
+ 6001 -> {sendMessage2Driver("二维码已过期")}
+ 1012 -> {sendMessage2Driver("当前用户下单路线非当前的车辆所属公司")}
+ else -> {
+ when (msg) {
+ "6002" -> {sendMessage2Driver("同一订单核销间隔时间需大于2分钟")}
+ "1009" -> {sendMessage2Driver("车票所选乘车日期非今日")}
+ "1005" -> {sendMessage2Driver("车辆未登录、或没有任务")}
+ "1006" -> {sendMessage2Driver("车票路线信息与当前车辆执行任务的路线信息不符合")}
+ "1008" -> {sendMessage2Driver("车票剩余可用次数为0")}
+ "6001" -> {sendMessage2Driver("二维码已过期")}
+ "1012" -> {sendMessage2Driver("当前用户下单路线非当前的车辆所属公司")}
+ else -> {
+ sendMessage2Driver(msg?:"")
+ }
+ }
+ }
+ }
+ }
+
+ override fun onError(message: String) {
+ ScannerChainLogManager.writeChainLog(TAG +"onError","/och-vehicle/api/scanner/device/writeOff接口请求错误orderNo:${orderNo}__uid:${uid}__reaseon:${message}")
+ sendMessage2Driver("网络错误")
+ }
+ }
+ )
+ }
+
+ private fun sendMessage2Driver(message:String){
+ val msg = WriteOffMsg(false, "", 0, "", message,"")
+ CallerLogger.d(M_BUS_P + TAG, "sendTaskDetailsToClients = " + GsonUtils.toJson(msg))
+ LanSocketManager.sendMsgToServer(msg)
+ ScannerChainLogManager.writeChainLog(TAG +"sendMessage2Driver","核验失败:message:${message}")
+ }
+ private fun sendMessage2DriverSuccess(message: PassengerWriteOffResponse.Result,orderNo: String){
+ val msg = WriteOffMsg(true, message.phone, message.ticketSize, message.ticketName, "",orderNo)
+ CallerLogger.d(M_BUS_P + TAG, "sendTaskDetailsToClients = " + GsonUtils.toJson(msg))
+ LanSocketManager.sendMsgToServer(msg)
+ ScannerChainLogManager.writeChainLog(TAG +"sendMessage2DriverSuccess","核验成功:message:${message}")
+ }
+
+
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/network/PassengerServiceManager.kt b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/network/PassengerServiceManager.kt
new file mode 100644
index 0000000000..de87800908
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/network/PassengerServiceManager.kt
@@ -0,0 +1,112 @@
+package com.mogo.och.shuttle.passenger.network
+
+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.commons.storage.SharedPrefsMgr
+import com.mogo.eagle.core.utilcode.util.StringUtils
+import com.mogo.eagle.core.utilcode.util.ToastUtils
+import com.mogo.och.common.module.constant.OchCommonConst
+import com.mogo.och.common.module.network.OchCommonServiceCallback
+import com.mogo.och.common.module.network.OchCommonSubscribeImpl
+import com.mogo.och.common.module.network.interceptor.transformTry
+import com.mogo.och.shuttle.passenger.bean.request.PassengerQueryLineRequest
+import com.mogo.och.shuttle.passenger.bean.request.PassengerWriteOffRequest
+import com.mogo.och.shuttle.passenger.bean.response.PassengerOperationStatusResponse
+import com.mogo.och.shuttle.passenger.bean.response.PassengerRoutesResponse
+import com.mogo.och.shuttle.passenger.bean.response.PassengerWriteOffResponse
+import com.mogo.och.shuttle.passenger.manager.scnner.ScannerChainLogManager
+
+/**
+ * Created on 2022/3/31
+ */
+object PassengerServiceManager {
+
+ private var driverSnCache = ""
+
+ private val TAG = "PassengerServiceManager"
+
+ private var mShuttleBusPassengerServiceApi =
+ MoGoRetrofitFactory.getInstance(OchCommonConst.getShuttleUrl()).create(
+ ServiceApi::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,
+ SharedPrefsMgr.getInstance().token,
+ PassengerQueryLineRequest(
+ driverAppSn
+ )
+ ).transformTry()
+ .subscribe(OchCommonSubscribeImpl(context, callback, "queryDriverSiteByCoordinate",false))
+ }
+
+ /**
+ * 查询司机端出车收车状态,以及车牌号
+ * @param context
+ * @param callback
+ */
+ @JvmStatic
+ fun queryDriverOperationStatus(
+ context: Context,
+ callback: OchCommonServiceCallback?
+ ) {
+ mShuttleBusPassengerServiceApi.queryDriverOperationStatus(
+ MoGoAiCloudClientConfig.getInstance().serviceAppId,
+ SharedPrefsMgr.getInstance().token,
+ driverAppSn
+ )
+ .transformTry()
+ .subscribe(OchCommonSubscribeImpl(context, callback, "queryDriverOperationStatus"))
+
+ }
+
+ /**
+ * 查询司机端出车收车状态,以及车牌号
+ * @param context
+ * @param callback
+ */
+ @JvmStatic
+ fun writeOffTicket(
+ context: Context,
+ ticketInfo: PassengerWriteOffRequest,
+ callback: OchCommonServiceCallback?,
+ ) {
+ ticketInfo.sn = driverAppSn
+ if(StringUtils.isEmpty(driverAppSn)){
+ ToastUtils.showShort("请链接司机屏${ticketInfo.uid}")
+ ScannerChainLogManager.writeChainLog(TAG +"onError","无司机屏sn请处理")
+ return
+ }
+ mShuttleBusPassengerServiceApi.writeOffTicket(
+ MoGoAiCloudClientConfig.getInstance().serviceAppId,
+ SharedPrefsMgr.getInstance().token,
+ ticketInfo
+ )
+ .transformTry()
+ .subscribe(OchCommonSubscribeImpl(context, callback, "writeOff"))
+
+ }
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/network/ServiceApi.java b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/network/ServiceApi.java
new file mode 100644
index 0000000000..4394df464f
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/com/mogo/och/shuttle/passenger/network/ServiceApi.java
@@ -0,0 +1,47 @@
+package com.mogo.och.shuttle.passenger.network;
+
+import com.mogo.och.shuttle.passenger.bean.request.PassengerQueryLineRequest;
+import com.mogo.och.shuttle.passenger.bean.request.PassengerWriteOffRequest;
+import com.mogo.och.shuttle.passenger.bean.response.PassengerOperationStatusResponse;
+import com.mogo.och.shuttle.passenger.bean.response.PassengerRoutesResponse;
+import com.mogo.och.shuttle.passenger.bean.response.PassengerWriteOffResponse;
+
+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 ServiceApi {
+ /**
+ * 查询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 PassengerQueryLineRequest 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);
+
+ /**
+ * 核销接口
+ */
+ @Headers({"Content-type:application/json;charset=UTF-8"})
+ @POST("/och-vehicle/api/scanner/device/writeOff")
+ Observable writeOffTicket(@Header ("appId") String appId, @Header("ticket") String ticket, @Body PassengerWriteOffRequest request);
+}
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/callback/IBusPassegerDriverStatusCallback.java b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/callback/IBusPassegerDriverStatusCallback.java
new file mode 100644
index 0000000000..73b44accf1
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/callback/IBusPassegerDriverStatusCallback.java
@@ -0,0 +1,9 @@
+package com.mogo.och.shuttle.passenger.callback;
+
+/**
+ * @author: wangmingjun
+ * @date: 2021/10/22
+ */
+public interface IBusPassegerDriverStatusCallback {
+ void changeOperationStatus(boolean changeStatus);
+}
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/callback/IBusPassengerADASStatusCallback.java b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/callback/IBusPassengerADASStatusCallback.java
new file mode 100644
index 0000000000..b410513938
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/callback/IBusPassengerADASStatusCallback.java
@@ -0,0 +1,18 @@
+package com.mogo.och.shuttle.passenger.callback;
+
+/**
+ * Created on 2022/3/31
+ *
+ * Model->Presenter回调:ADAS相关(自动驾驶状态回调,到达终点等等)
+ */
+public interface IBusPassengerADASStatusCallback {
+
+ // 自动驾驶可用状态
+ void onAutopilotEnable();
+
+ // 自动驾驶不可用状态
+ void onAutopilotDisable();
+
+ // 自动驾驶运行中
+ void onAutopilotRunning();
+}
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/callback/IBusPassengerAutopilotPlanningCallback.java b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/callback/IBusPassengerAutopilotPlanningCallback.java
new file mode 100644
index 0000000000..37d813d299
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/callback/IBusPassengerAutopilotPlanningCallback.java
@@ -0,0 +1,9 @@
+package com.mogo.och.shuttle.passenger.callback;
+
+/**
+ * Created on 2022/3/31
+ */
+public interface IBusPassengerAutopilotPlanningCallback {
+ void routePlanningToNextStationChanged(long meters, long timeInSecond);
+
+}
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/callback/IBusPassengerControllerStatusCallback.java b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/callback/IBusPassengerControllerStatusCallback.java
new file mode 100644
index 0000000000..29407a28dc
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/callback/IBusPassengerControllerStatusCallback.java
@@ -0,0 +1,13 @@
+package com.mogo.och.shuttle.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 {
+ // 自车定位
+ void onCarLocationChanged(MogoLocation location);
+}
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/callback/IBusPassengerRouteLineInfoCallback.java b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/callback/IBusPassengerRouteLineInfoCallback.java
new file mode 100644
index 0000000000..aeebb9dfd4
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/callback/IBusPassengerRouteLineInfoCallback.java
@@ -0,0 +1,16 @@
+package com.mogo.och.shuttle.passenger.callback;
+
+import com.mogo.och.data.bean.BusStationBean;
+
+import java.util.List;
+
+/**
+ * @author: wangmingjun
+ * @date: 2022/4/6
+ */
+public interface IBusPassengerRouteLineInfoCallback {
+ void updateLineInfo(String lineName);
+ void updateStationsInfo(List stations, int currentStationIndex, boolean isArrived);
+ void showNoTaskView();
+ void hideNoTaskView();
+}
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/model/BusPassengerModel.java b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/model/BusPassengerModel.java
new file mode 100644
index 0000000000..5e5eac6004
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/model/BusPassengerModel.java
@@ -0,0 +1,495 @@
+package com.mogo.och.shuttle.passenger.model;
+
+import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS_P;
+import static com.mogo.och.shuttle.passenger.constant.BusPassengerConst.QUERY_BUS_P_STATION_DELAY;
+import static com.mogo.och.shuttle.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.mogo.aicloud.services.socket.MogoAiCloudSocketManager;
+import com.mogo.commons.module.intent.IMogoIntentListener;
+import com.mogo.commons.module.intent.IntentManager;
+import com.mogo.eagle.core.function.api.telematic.IReceivedMsgListener;
+import com.mogo.eagle.core.function.call.telematic.CallerTelematicListenerManager;
+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.GsonUtils;
+import com.mogo.eagle.core.utilcode.util.StringUtils;
+import com.mogo.eagle.core.utilcode.util.ToastUtils;
+import com.mogo.och.common.module.manager.autopilot.autopilot.IOchAutopilotStatusListener;
+import com.mogo.och.common.module.manager.autopilot.autopilot.OchAutoPilotStatusListenerManager;
+import com.mogo.och.common.module.manager.autopilot.location.OchLocationManager;
+import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager;
+import com.mogo.och.common.module.manager.socket.lan.LanSocketManager;
+import com.mogo.och.common.module.manager.socket.lan.bean.BusinessType;
+import com.mogo.och.common.module.voice.VoiceNotice;
+import com.mogo.och.shuttle.passenger.R;
+import com.mogo.och.common.module.manager.socket.lan.bean.AppConnectMsg;
+import com.mogo.och.common.module.manager.socket.lan.bean.BaseDPMsg;
+import com.mogo.och.common.module.manager.socket.lan.bean.DPMsgType;
+import com.mogo.och.common.module.manager.socket.lan.bean.TaskDetailsMsg;
+import com.mogo.och.common.module.manager.socket.cloud.OCHSocketMessageManager;
+import com.mogo.och.common.module.constant.OchCommonConst;
+import com.mogo.och.common.module.manager.distance.IDistanceListener;
+import com.mogo.och.common.module.manager.distance.TrajectoryAndDistanceManager;
+import com.mogo.och.common.module.utils.DateTimeUtil;
+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.utilcode.mogo.logger.CallerLogger;
+import com.mogo.eagle.core.utilcode.util.NetworkUtils;
+import com.mogo.och.shuttle.passenger.bean.response.PassengerOperationStatusResponse;
+import com.mogo.och.shuttle.passenger.bean.response.PassengerRoutesResponse;
+import com.mogo.och.shuttle.passenger.callback.IBusPassegerDriverStatusCallback;
+import com.mogo.och.shuttle.passenger.callback.IBusPassengerADASStatusCallback;
+import com.mogo.och.shuttle.passenger.callback.IBusPassengerAutopilotPlanningCallback;
+import com.mogo.och.shuttle.passenger.callback.IBusPassengerControllerStatusCallback;
+import com.mogo.och.shuttle.passenger.callback.IBusPassengerRouteLineInfoCallback;
+import com.mogo.och.shuttle.passenger.constant.BusPassengerConst;
+import com.mogo.och.shuttle.passenger.network.BusPassengerModelLoopManager;
+import com.mogo.och.common.module.network.OchCommonServiceCallback;
+import com.mogo.och.common.module.manager.socket.cloud.AbnormalFactorsLoopManager;
+import com.mogo.och.data.bean.BusRoutesResult;
+import com.mogo.och.data.bean.BusStationBean;
+import com.mogo.och.data.bean.BusTransferData;
+import com.mogo.och.shuttle.passenger.network.PassengerServiceManager;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Created on 2022/3/31
+ */
+public class BusPassengerModel {
+ private static final String TAG = BusPassengerModel.class.getSimpleName();
+ 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 BusRoutesResult routesResult = null;
+
+ List mStations = new ArrayList<>();
+ private int mNextStationIndex = 0;// 要到达站的index
+
+ private volatile boolean isGoingToNextStation = false;
+
+ 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();
+ queryDriverOperationStatus();
+ queryDriverByLocalDriver();
+ startOrStopOrderLoop(true);
+ }
+
+ private void queryDriverByLocalDriver() {
+ //本地去请求司机端
+ TaskDetailsMsg msg = new TaskDetailsMsg("task", BusinessType.shuttle);
+
+ LanSocketManager.sendMsgToServer(msg);
+ }
+
+ 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() {
+ PassengerServiceManager.queryDriverOperationStatus(mContext
+ , new OchCommonServiceCallback() {
+ @Override
+ public void onSuccess(PassengerOperationStatusResponse data) {
+ if (data == null || data.data == null) return;
+ if (mDriverStatusCallback != null) {
+ CallerLogger.d( M_BUS_P + TAG, "queryDriverOperationStatus = %s", data.data.plateNumber );
+ mDriverStatusCallback.changeOperationStatus(data.data.driverStatus == 1);
+ }
+ }
+
+ @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 msg) {
+ //延迟3s再次查询
+ queryDriverOperationDelay();
+ }
+ });
+ }
+
+ public void queryDriverSiteByCoordinate(){
+ PassengerServiceManager.queryDriverSiteByCoordinate(mContext
+ , new OchCommonServiceCallback() {
+ @Override
+ public void onSuccess(PassengerRoutesResponse data) {
+ if ( data == null || data.getResult() == null) {
+ CallerLogger.d( M_BUS_P + TAG, "queryDriverSiteByCoordinate = null");
+ clearLocalRouteResult();
+ return;
+ }
+ if (routesResult != null && data.getResult().equals(routesResult)){
+ CallerLogger.d( M_BUS_P + TAG, "queryDriverSiteByCoordinate = not update");
+ return;
+ }
+
+ OchChainLogManager.writeChainLog("线路发生变化",data.toString());
+
+ if (routesResult != null &&
+ routesResult.getWriteVersion() < data.getResult().getWriteVersion()){
+ routesResult = data.getResult();
+ }
+
+ if (routesResult == null){
+ routesResult = data.getResult();
+ }
+
+ updatePassengerRouteInfo(routesResult);
+ }
+
+ @Override
+ public void onError() {
+ CallerLogger.d( M_BUS_P + TAG, "queryDriverSiteByCoordinate = onError ="
+ + ", sn = " +PassengerServiceManager.INSTANCE.getDriverAppSn());
+ queryDriverByLocalDriver();
+ }
+
+ @Override
+ public void onFail(int code, String msg) {
+ CallerLogger.d( M_BUS_P + TAG, "queryDriverSiteByCoordinate = %s", msg
+ + ", sn = " +PassengerServiceManager.INSTANCE.getDriverAppSn());
+ if (code == 1003){
+ queryDriverOperationDelay();
+ }
+ if (PassengerServiceManager.INSTANCE.getDriverAppSn().isEmpty()){
+ //此处拦截是为了防止过程中乘客屏和司机端断连,拿不到司机端sn, 造成请求失败去刷新了界面
+ return;
+ }
+ if (code == 1003){
+ routesResult = null;
+ cleanStation("queryDriverSiteByCoordinate 1003");
+ return;
+ }
+ queryDriverByLocalDriver();
+ }
+ });
+ }
+
+ private void clearLocalRouteResult() {
+ if (routesResult != null) {
+ routesResult = null;
+ }
+ mNextStationIndex = 0;
+ cleanStation("queryDriverSiteByCoordinate");
+ if (mRouteLineInfoCallback != null){
+ mRouteLineInfoCallback.showNoTaskView();
+ }
+ }
+
+ private void updatePassengerRouteInfo(BusRoutesResult result) {
+ if (result == null){
+ clearLocalRouteResult();
+ return;
+ }
+ CallerLogger.d( M_BUS_P + TAG, "queryDriverSiteByCoordinate = update");
+ routesResult = result;
+
+ if (mRouteLineInfoCallback != null){
+ mRouteLineInfoCallback.updateLineInfo(result.getName());
+ mRouteLineInfoCallback.hideNoTaskView();
+ if (result.getSites() != null){
+ List stations = result.getSites();
+ mStations.clear();
+ mStations.addAll(stations);
+ for (int i = 0; i< stations.size(); i++){
+ BusStationBean station = stations.get(i);
+ if (station.getDrivingStatus() == STATION_STATUS_STOPPED && station.isLeaving() && i+1 < stations.size()){
+ Logger.d(M_BUS_P + TAG, "order = station= leave");
+ isGoingToNextStation = true;
+ mRouteLineInfoCallback.updateStationsInfo(stations,i+1,false);
+ mNextStationIndex = i+1;
+ BusStationBean startStation = mStations.get(i);
+ BusStationBean endStation = mStations.get(i+1);
+ setTrajectoryStation(startStation, endStation, result.getLineId());
+ return;
+ }else if (station.getDrivingStatus() == STATION_STATUS_STOPPED && !station.isLeaving()){
+ if (i == stations.size() - 1) {
+ cleanStation("updatePassengerRouteInfo最后一个站点");
+ }
+
+ isGoingToNextStation = false;
+ Logger.d(M_BUS_P + TAG, "order = station= arrive");
+ mRouteLineInfoCallback.updateStationsInfo(stations,i,true);
+ return;
+ }
+ }
+ }
+ }
+
+ }
+
+ public void release() {
+ releaseListeners();
+ cleanStation("release");
+ 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接口
+ OchAutoPilotStatusListenerManager.INSTANCE.addListener(TAG,mGoAutopilotStatusListener);
+ IntentManager.getInstance().registerIntentListener(ConnectivityManager.CONNECTIVITY_ACTION, mNetWorkIntentListener );
+ // 定位监听
+ OchLocationManager.addGCJ02Listener(TAG, 3,mMapLocationListener);
+
+
+ //监听司机端消息
+ CallerTelematicListenerManager.INSTANCE.addListener(TAG,mReceivedMsgListener);
+
+ AbnormalFactorsLoopManager.INSTANCE.startLoopAbnormalFactors(mContext);
+ TrajectoryAndDistanceManager.INSTANCE.addDistanceListener(TAG, trajectoryListener);
+ }
+
+ private void releaseListeners() {
+
+ // 注销定位监听
+ OchLocationManager.removeGCJ02Listener(TAG);
+
+ MogoAiCloudSocketManager.getInstance(mContext)
+ .unregisterLifecycleListener(10010);
+
+ OchAutoPilotStatusListenerManager.INSTANCE.removeListener(mGoAutopilotStatusListener);
+
+ AbnormalFactorsLoopManager.INSTANCE.stopLoopAbnormalFactors();
+
+ CallerTelematicListenerManager.INSTANCE.removeListener(TAG);
+ CallerTelematicListenerManager.INSTANCE.removeListener(TAG);
+ }
+
+ private final IDistanceListener trajectoryListener = new IDistanceListener() {
+ @Override
+ public void stationDistanceCallback(float distance) {
+
+ }
+ @Override
+ public void distanceCallback(float distance) {
+ double lastTime = distance / BusPassengerConst.BUS_AVERAGE_SPEED * 3.6; //秒
+ CallerLogger.d(M_BUS_P + TAG, "轨迹排查==lastSumLength = "+distance);
+ if(routesResult!=null){
+ for (BusStationBean site : routesResult.getSites()) {
+ if (site.getDrivingStatus() == BusPassengerConst.STATION_STATUS_STOPPED && !site.isLeaving()) {
+ return;
+ }
+ }
+ }
+ // 小于200m 播报站点介绍
+ if(distance<200){
+ BusStationBean stationNext = mStations.get(mNextStationIndex);
+ if(!stationNext.isPlayTts()){
+ if (!StringUtils.isEmpty(stationNext.getIntroduction())) {
+ VoiceNotice.showNotice(stationNext.getIntroduction());
+ stationNext.setPlayTts(true);
+ }
+ }
+ }
+ mAutopilotPlanningCallback.routePlanningToNextStationChanged(
+ (long)distance, (long)lastTime
+ );
+ }
+ };
+
+ private final IReceivedMsgListener mReceivedMsgListener = new IReceivedMsgListener() {
+ @Override
+ public void onDemoMode(boolean isDemoMode) {
+
+ }
+
+ @Override
+ public void onReceivedServerSn(@Nullable String sn) {
+ Logger.d(SceneConstant.M_BUS_P + TAG, "司机屏sn:"+sn );
+ }
+
+ @Override
+ public void onReceivedMsg(int type, @NonNull byte[] byteArray) {
+ if (OchCommonConst.BUSINESS_STRING == type) {
+
+ BaseDPMsg baseMsg = GsonUtils.fromJson(new String(byteArray), BaseDPMsg.class);
+ Logger.d(SceneConstant.M_BUS_P + TAG, "onReceivedMsg = " + GsonUtils.toJson(baseMsg));
+
+ if (baseMsg != null && baseMsg.getType() == DPMsgType.TYPE_COMMON.getType()) {
+ AppConnectMsg msg = GsonUtils.fromJson(new String(byteArray), AppConnectMsg.class);
+ if (msg != null && msg.isViewShow()) { //消息盒子显示内容
+ OCHSocketMessageManager.INSTANCE.pushAppOperationalMsgBox(
+ DateTimeUtil.getCurrentTimeStamp(), msg.getMsg(),
+ OCHSocketMessageManager.OPERATION_SYSTEM);
+ }
+ } else if (baseMsg != null && baseMsg.getType() == DPMsgType.TYPE_TASK_DETAILS.getType()) {
+ TaskDetailsMsg msg = GsonUtils.fromJson(new String(byteArray), TaskDetailsMsg.class);
+
+ Logger.d(SceneConstant.M_BUS_P + TAG, "onReceivedMsg = " + GsonUtils.toJson(msg));
+ if (msg == null || msg.getMsg().isEmpty()) {
+ clearLocalRouteResult();
+ return;
+ }
+ BusTransferData result = GsonUtils.fromJson(msg.getMsg(), BusTransferData.class);
+ if (msg != null && mDriverStatusCallback != null) {
+ mDriverStatusCallback.changeOperationStatus(result.getLoginStatus() == 1);
+ }
+ if (result != null) { //已司机端传来的为准
+ routesResult = result.getRoutesResult();
+ updatePassengerRouteInfo(routesResult);
+ }
+ }
+ }
+ }
+ };
+
+
+ //监听网络变化,避免启动机器时无网导致无法更新订单信息
+ private final IMogoIntentListener mNetWorkIntentListener = new IMogoIntentListener() {
+ @Override
+ public void onIntentReceived( String intentStr, Intent intent ) {
+ CallerLogger.d( M_BUS_P + TAG, "onIntentReceived = %s", intentStr );
+ if ( ConnectivityManager.CONNECTIVITY_ACTION.equals( intentStr ) ) {
+ if ( NetworkUtils.isConnected( mContext ) ) {
+ queryDriverOperationStatus();
+ }
+ }
+ }
+ };
+
+ private final IMoGoChassisLocationGCJ02Listener mMapLocationListener = new IMoGoChassisLocationGCJ02Listener() {
+ @Override
+ public void onChassisLocationGCJ02(@Nullable MogoLocation gnssInfo) {
+ if (null == gnssInfo) return;
+ for (IBusPassengerControllerStatusCallback callback :mControllerStatusCallbackMap.values()){
+ callback.onCarLocationChanged(gnssInfo);
+ }
+ }
+ };
+
+ private final IOchAutopilotStatusListener mGoAutopilotStatusListener = new IOchAutopilotStatusListener(){
+
+ @Override
+ public void onAutopilotStatusResponse(int state) {
+ if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) {
+ //2022.7.20 自动驾驶更换成带档位的
+ if (mADASStatusCallback != null) mADASStatusCallback.onAutopilotRunning();
+ } else{
+ if (FunctionBuildConfig.isDemoMode &&
+ mNextStationIndex>= 0 && mNextStationIndex <= mStations.size() - 1
+ && isGoingToNextStation){
+ Logger.d(M_BUS_P + TAG, "FunctionBuildConfig.isDemoMode is true");
+ return;
+ }
+
+ if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE) {
+ if (mADASStatusCallback != null) mADASStatusCallback.onAutopilotEnable();
+ } else if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE) {
+ if (mADASStatusCallback != null) mADASStatusCallback.onAutopilotDisable();
+ }else if (state == IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING){
+ if (mADASStatusCallback != null) mADASStatusCallback.onAutopilotRunning();
+ }
+ }
+ }
+ };
+
+ private void startOrStopOrderLoop(boolean start) {
+ CallerLogger.d(M_BUS_P + TAG, "startOrStopOrderLoop() " + start);
+ if (start) {
+ BusPassengerModelLoopManager.getInstance().startQueryDriverLineLoop();
+ } else {
+ BusPassengerModelLoopManager.getInstance().stopQueryDriverLineLoop();
+ }
+ }
+
+ private void setTrajectoryStation(
+ BusStationBean startStationInfo ,
+ BusStationBean endStationInfo,
+ int lineId
+ ) {
+ MogoLocation startStation = new MogoLocation();
+ startStation.setLongitude(startStationInfo.getGcjLon());
+ startStation.setLatitude(startStationInfo.getGcjLat());
+ MogoLocation endStation = new MogoLocation();
+ endStation.setLongitude(endStationInfo.getGcjLon());
+ endStation.setLatitude(endStationInfo.getGcjLat());
+ TrajectoryAndDistanceManager.INSTANCE.setStationPoint(startStation, endStation, (long)lineId);
+ }
+
+ private void cleanStation(String type) {
+ CallerLogger.d(M_BUS_P + TAG, "清理站点:"+type);
+ TrajectoryAndDistanceManager.INSTANCE.setStationPoint(null, null, -1L);
+ }
+
+}
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/network/BusPassengerModelLoopManager.java b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/network/BusPassengerModelLoopManager.java
new file mode 100644
index 0000000000..09f7837cf5
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/network/BusPassengerModelLoopManager.java
@@ -0,0 +1,58 @@
+package com.mogo.och.shuttle.passenger.network;
+
+import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
+import com.mogo.och.shuttle.passenger.model.BusPassengerModel;
+
+import java.util.concurrent.TimeUnit;
+
+import io.reactivex.Observable;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.CompositeDisposable;
+import io.reactivex.disposables.Disposable;
+import io.reactivex.schedulers.Schedulers;
+
+import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS_P;
+import static com.mogo.och.shuttle.passenger.constant.BusPassengerConst.LOOP_DELAY;
+import static com.mogo.och.shuttle.passenger.constant.BusPassengerConst.LOOP_LINE_2S;
+
+/**
+ * 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; //心跳轮询
+
+ public void startQueryDriverLineLoop() {
+ if (mQueryLineDisposable != null && !mQueryLineDisposable.isDisposed()) {
+ return;
+ }
+ CallerLogger.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.i(M_BUS_P + TAG, "stopQueryDriverLineLoop()");
+ mQueryLineDisposable.dispose();
+ mQueryLineDisposable = null;
+ }
+ }
+
+}
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/presenter/BaseBusPassengerPresenter.java b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/presenter/BaseBusPassengerPresenter.java
new file mode 100644
index 0000000000..2d5a815653
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/presenter/BaseBusPassengerPresenter.java
@@ -0,0 +1,192 @@
+package com.mogo.och.shuttle.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.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.shuttle.passenger.callback.IBusPassegerDriverStatusCallback;
+import com.mogo.och.shuttle.passenger.callback.IBusPassengerADASStatusCallback;
+import com.mogo.och.shuttle.passenger.callback.IBusPassengerAutopilotPlanningCallback;
+import com.mogo.och.shuttle.passenger.callback.IBusPassengerControllerStatusCallback;
+import com.mogo.och.shuttle.passenger.callback.IBusPassengerRouteLineInfoCallback;
+import com.mogo.och.shuttle.passenger.model.BusPassengerModel;
+import com.mogo.och.shuttle.passenger.ui.BusPassengerRouteFragment;
+import com.mogo.och.data.bean.BusStationBean;
+
+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.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);
+ }
+
+ @Override
+ public void onAutopilotEnable() {
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mView != null) {
+ mView.onAutopilotStatusChanged(
+ IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE);
+ }
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+ }
+
+ @Override
+ public void onAutopilotDisable() {
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mView != null) {
+ mView.onAutopilotStatusChanged(
+ IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE);
+ }
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+ }
+
+ @Override
+ public void onAutopilotRunning() {
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mView != null) {
+ mView.onAutopilotStatusChanged(
+ IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING);
+ }
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+ }
+
+ @Override
+ public void onCarLocationChanged(MogoLocation location) {
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (location != null && mView != null) {
+ mView.onCarLocationChanged(location);
+ }
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+ }
+
+ @Override
+ public void changeOperationStatus(boolean changeStatus) {
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mView != null) {
+ mView.changeOperationStatus(changeStatus);
+ }
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+ }
+
+ @Override
+ public void updateLineInfo(String lineName) {
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mView != null) {
+ mView.updateLineInfo(lineName);
+ }
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+ }
+
+ @Override
+ public void updateStationsInfo(List stations, int currentStationIndex, boolean isArrived) {
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mView != null) {
+ mView.updateStationsInfo(stations, currentStationIndex, isArrived);
+ }
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+ }
+
+ @Override
+ public void showNoTaskView() {
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mView != null) {
+ mView.showNoTaskView();
+ }
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+ }
+
+ @Override
+ public void hideNoTaskView() {
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mView != null) {
+ mView.hideNoTaskView();
+ }
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+ }
+
+ @Override
+ public void routePlanningToNextStationChanged(long meters, long timeInSecond) {
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mView != null) {
+ mView.updateRoutePlanningToNextStation(meters, timeInSecond);
+ }
+ }
+ }, UiThreadHandler.MODE.QUEUE);
+ }
+}
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/ui/BusPBlueToothView.kt b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/ui/BusPBlueToothView.kt
new file mode 100644
index 0000000000..985057174c
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/ui/BusPBlueToothView.kt
@@ -0,0 +1,36 @@
+package com.mogo.och.shuttle.passenger.ui
+
+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.shuttle.passenger.R
+import kotlinx.android.synthetic.main.shuttle_p_jl_view_blue_tooth.view.blueView
+
+/**
+ * 魔戒蓝牙控件
+ * 放置于StatusBar右侧位置
+ */
+class BusPBlueToothView @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0
+) : BlueToothView(context, attrs, defStyleAttr),IMoGoDevaToolsListener {
+
+ init {
+ LayoutInflater.from(context).inflate(R.layout.shuttle_p_jl_view_blue_tooth, this, true)
+ }
+
+ override fun mofangStatus(status: Boolean) {
+ ThreadUtils.runOnUiThread {
+ if (status) {
+ blueView.setImageResource(R.drawable.shuttle_p_jl_blue_tooth_close)
+ } else {
+ blueView.setImageResource(R.drawable.shuttle_p_jl_blue_tooth_open)
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/ui/BusPStatusBarView.kt b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/ui/BusPStatusBarView.kt
new file mode 100644
index 0000000000..cd2c21f70a
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/ui/BusPStatusBarView.kt
@@ -0,0 +1,70 @@
+package com.mogo.och.shuttle.passenger.ui
+
+import android.annotation.*
+import android.content.Context
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.constraintlayout.widget.ConstraintLayout
+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.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.AppUtils
+import com.mogo.och.shuttle.passenger.R
+import kotlinx.android.synthetic.main.shuttle_p_jl_view_status_bar.view.tv_shuttle_b1_p_version
+import kotlinx.coroutines.*
+import me.jessyan.autosize.utils.AutoSizeUtils
+
+/**
+ * @author: wangmingjun
+ * @date: 2023/2/14
+ */
+class BusPStatusBarView @JvmOverloads constructor(
+ context: Context, attrs: AttributeSet? = null
+) : ConstraintLayout(context, attrs), IViewControlListener, IMoGoSkinModeChangeListener{
+
+ companion object {
+ const val TAG = "BusPStatusBarView"
+ }
+
+ init {
+ LayoutInflater.from(context).inflate(R.layout.shuttle_p_jl_view_status_bar, this, true)
+ setBackgroundResource(R.drawable.shuttle_p_jl_bg_status_bar)
+ isClickable = true
+ isFocusable = true
+
+ tv_shuttle_b1_p_version.text = "版本:${AppUtils.getAppVersionName()}"
+ }
+
+
+ @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)
+ }
+
+ 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()
+ }
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/ui/BusPassengerBaseFragment.java b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/ui/BusPassengerBaseFragment.java
new file mode 100644
index 0000000000..a15e0da496
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/ui/BusPassengerBaseFragment.java
@@ -0,0 +1,96 @@
+package com.mogo.och.shuttle.passenger.ui;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.widget.FrameLayout;
+
+import androidx.annotation.NonNull;
+
+import com.mogo.commons.mvp.IView;
+import com.mogo.commons.mvp.MvpFragment;
+
+import com.mogo.commons.mvp.Presenter;
+import com.mogo.eagle.core.function.hmi.ui.widget.RomaPassengerView;
+import com.mogo.eagle.core.function.view.MapBizView;
+import com.mogo.och.shuttle.passenger.R;
+
+/**
+ * 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 FrameLayout flContainer;
+ private RomaPassengerView romaPView;
+
+ @Override
+ protected int getLayoutId() {
+ return R.layout.shuttle_p_jl_base_fragment;
+ }
+
+ @Override
+ public String getTagName() {
+ return TAG;
+ }
+
+ @Override
+ protected void initViews() {
+ mapBizView = findViewById(R.id.mapBizView);
+
+ showRouteFragment();
+ }
+
+ @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);
+ }
+}
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/ui/BusPassengerRouteFragment.java b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/ui/BusPassengerRouteFragment.java
new file mode 100644
index 0000000000..0009a3b75a
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/ui/BusPassengerRouteFragment.java
@@ -0,0 +1,383 @@
+package com.mogo.och.shuttle.passenger.ui;
+
+import android.content.Context;
+import android.graphics.drawable.AnimationDrawable;
+import android.os.Bundle;
+import android.text.Html;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.widget.AppCompatImageView;
+import androidx.appcompat.widget.AppCompatTextView;
+import androidx.constraintlayout.widget.ConstraintLayout;
+import androidx.constraintlayout.widget.Group;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.amap.api.maps.model.LatLng;
+import com.elegant.utils.UiThreadHandler;
+import com.mogo.eagle.core.data.enums.SidePattern;
+import com.mogo.eagle.core.data.map.MogoLocation;
+import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener;
+import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager;
+import com.mogo.eagle.core.function.hmi.ui.setting.ToggleDebugView;
+import com.mogo.map.overlay.IMoGoOverlayManager;
+import com.mogo.och.common.module.utils.ResourcesUtils;
+import com.mogo.och.shuttle.passenger.R;
+import com.mogo.och.shuttle.passenger.ui.adapter.BusPassengerLineStationsAdapter;
+import com.mogo.och.shuttle.passenger.presenter.BaseBusPassengerPresenter;
+import com.mogo.och.shuttle.passenger.ui.layoutmanager.CenterLayoutManager;
+import com.mogo.och.common.module.wigets.mapdirectionview.MapDirectionView;
+import com.mogo.och.common.module.utils.NumberFormatUtil;
+import com.mogo.och.common.module.wigets.MarqueeTextView;
+import com.mogo.och.common.module.wigets.OCHGradientTextView;
+import com.mogo.och.data.bean.BusStationBean;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author: wangmingjun
+ * @date: 2022/4/12
+ */
+public class BusPassengerRouteFragment extends
+ BusPassengerBaseFragment {
+
+ public static final String TAG = "BusPassengerRouteFragment";
+
+ private final List mStationsList = new ArrayList<>();
+
+ private OCHGradientTextView mSpeedTv;
+ private ConstraintLayout mNoLineInfoView;
+ private MarqueeTextView mLineName;
+ private Group mRouteInfoView;
+ private RecyclerView mStationsListRv;
+ private MapDirectionView mMapDirectionView;
+ private BusPassengerLineStationsAdapter mAdapter;
+ private TextView emptyTv;
+ private AppCompatImageView mAutopilotIv;
+ private AppCompatTextView mCurrentArriveStation;
+ private AppCompatTextView mCurrentArriveStationTitle;
+ private AppCompatTextView mCurrentArriveTip;
+ private AppCompatImageView mSpeakArrivedIv;
+
+ /**
+ * 改变自动驾驶状态
+ *
+ * @param status 2 - running 1 - enable 2 - disable
+ */
+ private int mPrevAPStatus = -1;
+
+ @Override
+ public int getStationPanelViewId() {
+ return R.layout.shuttle_p_jl_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);
+ mSpeedTv.setVertrial(true);
+ mSpeedTv.setmColorList(new int[]{ResourcesUtils.getColor(R.color.shuttle_p_jl_speed_color_start),
+ ResourcesUtils.getColor(R.color.shuttle_p_jl_speed_color_end)});
+
+ mNoLineInfoView =findViewById(R.id.bus_p_no_order_data_view);
+ emptyTv = findViewById(R.id.no_order_data_tv);
+
+ mLineName = findViewById(R.id.bus_p_line_name_tv);
+ mAutopilotIv = findViewById(R.id.auto_status_iv);
+ 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);
+ mSpeakArrivedIv = findViewById(R.id.speak_arrived_iv);
+
+ 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);
+
+ mSpeedTv.setOnLongClickListener(v -> {
+ Context context = getContext();
+ if(context!=null){
+ ToggleDebugView.Companion.
+ getToggleDebugView().toggle(context, Gravity.RIGHT, SidePattern.RIGHT);
+ }
+ return true;
+ });
+ }
+
+ @Override
+ protected void initViews(Bundle savedInstanceState) {
+ super.initViews(savedInstanceState);
+ mMapDirectionView = findViewById(R.id.bus_p_line_map_view);
+ mMapDirectionView.onCreateView(savedInstanceState);
+ }
+
+ @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 onDestroyView() {
+ if (mPresenter != null) {
+ mPresenter.onDestroy(this);
+ }
+ IMoGoOverlayManager overlayManager = CallerMapUIServiceManager.INSTANCE.getOverlayManager();
+ if(overlayManager!=null) {
+ overlayManager.removeAllLines();
+ overlayManager.removeAllPoints();
+ }
+ super.onDestroyView();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (mMapDirectionView != null) {
+ mMapDirectionView.onDestroy();
+ }
+ }
+
+ 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) {
+ emptyTv.setText(getString(R.string.shuttle_p_jl_no_out));
+ mNoLineInfoView.setVisibility(View.VISIBLE);
+ mRouteInfoView.setVisibility(View.GONE);
+ mLineName.setText(getContext().getString(R.string.shuttle_p_jl_no_line));
+ updateArrivedStation(null,0,true);
+ clearMapView();
+ clearMapMarkers();
+ }
+ }
+
+ public void showNoTaskView(){
+ if (mNoLineInfoView.getVisibility() == View.GONE){
+ mNoLineInfoView.setVisibility(View.VISIBLE);
+ mRouteInfoView.setVisibility(View.GONE);
+ mLineName.setText(getContext().getString(R.string.shuttle_p_jl_no_line));
+ updateArrivedStation(null,0,true);
+ clearMapView();
+ clearMapMarkers();
+ }
+ emptyTv.setText(getString(R.string.shuttle_p_jl_no_task));
+ }
+
+ public void hideNoTaskView(){
+ if (mNoLineInfoView.getVisibility() == View.VISIBLE){
+ mNoLineInfoView.setVisibility(View.GONE);
+ }
+ if (mRouteInfoView.getVisibility() == View.GONE){
+ mRouteInfoView.setVisibility(View.VISIBLE);
+ }
+ }
+
+ public void updateLineInfo(String lineName) {
+ mLineName.setText(lineName);
+ }
+
+ /**
+ *
+ * @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 清楚路径 清空路径点
+ 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 = 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.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);
+ }
+ }
+
+ public void updateArrivedStation(String station,int currentIndex,boolean isArrived){
+ if (null == station){
+ mCurrentArriveStation.setText("----");
+ mCurrentArriveStationTitle.setText(ResourcesUtils.getString(R.string.shuttle_p_jl_cur_station_title));
+ mCurrentArriveTip.setText(ResourcesUtils.getString(R.string.shuttle_p_jl_cur_station_arrived_tip));
+ mCurrentArriveTip.setBackgroundResource(R.drawable.shuttle_p_jl_cur_station_arrived_bg);
+ handleArrivingSpeakIconDrawable();
+ }else {
+ mCurrentArriveStation.setText(station);
+ if (currentIndex == 0){
+ mCurrentArriveStationTitle.setText(ResourcesUtils.getString(R.string.shuttle_p_jl_cur_station_title));
+ mCurrentArriveTip.setText(ResourcesUtils.getString(R.string.shuttle_p_jl_cur_station_arrived_tip));
+ mCurrentArriveTip.setBackgroundResource(R.drawable.shuttle_p_jl_cur_station_arrived_bg);
+ handleArrivingSpeakIconDrawable();
+ return;
+ }
+ if (isArrived){
+ mCurrentArriveStationTitle.setText(ResourcesUtils.getString(R.string.shuttle_p_jl_cur_station_title));
+ mCurrentArriveTip.setText(ResourcesUtils.getString(R.string.shuttle_p_jl_cur_station_arrived_tip));
+ mCurrentArriveTip.setBackgroundResource(R.drawable.shuttle_p_jl_cur_station_arrived_bg);
+ handleArrivedSpeakIconDrawable();
+ }else {
+ mCurrentArriveStationTitle.setText(ResourcesUtils.getString(R.string.shuttle_p_jl_cur_next_station_title));
+ mCurrentArriveTip.setBackgroundResource(R.drawable.shuttle_p_jl_cur_station_un_arrived_bg);
+ handleArrivingSpeakIconDrawable();
+ }
+ }
+
+ }
+
+ private void handleArrivedSpeakIconDrawable(){
+ AnimationDrawable animationDrawable = (AnimationDrawable) mSpeakArrivedIv.getDrawable();
+ animationDrawable.start();
+ mSpeakArrivedIv.setVisibility(View.VISIBLE);
+ }
+
+ private void handleArrivingSpeakIconDrawable(){
+ AnimationDrawable animationDrawable = (AnimationDrawable) mSpeakArrivedIv.getDrawable();
+ animationDrawable.stop();
+ mSpeakArrivedIv.setVisibility(View.GONE);
+ }
+
+ public void updateRoutePlanningToNextStation(long meters, long timeInSecond){
+ //更新进度条
+ 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) + " " + " 分钟 ";
+ String str = dis+disUnit+" | "+(int)Math.ceil((double)timeInSecond/ 60f)+"分钟";
+ mCurrentArriveTip.setText(Html.fromHtml(str));
+ }
+
+ public void onAutopilotStatusChanged(int status) {
+ UiThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ // 3. 其他过程直接更新
+ if (mPrevAPStatus != status){
+ AutopilotStatusChanged(status);
+ }
+ mPrevAPStatus = status;
+ }
+ });
+ }
+
+ public void AutopilotStatusChanged(int status) {
+ if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING == status) {
+ mAutopilotIv.setImageResource(R.drawable.shuttle_p_jl_auto_open);
+ } else {
+ mAutopilotIv.setImageResource(R.drawable.shuttle_p_jl_auto_close);
+ }
+ }
+}
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/ui/BusPassengerTrafficLightView.kt b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/ui/BusPassengerTrafficLightView.kt
new file mode 100644
index 0000000000..f2178f347d
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/ui/BusPassengerTrafficLightView.kt
@@ -0,0 +1,181 @@
+package com.mogo.och.shuttle.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.shuttle.passenger.R
+import kotlinx.android.synthetic.main.shuttle_p_jl_traffic_light_view.view.bus_p_traffic_light_bg
+import kotlinx.android.synthetic.main.shuttle_p_jl_traffic_light_view.view.bus_p_traffic_light_iv
+import kotlinx.android.synthetic.main.shuttle_p_jl_traffic_light_view.view.bus_p_traffic_light_time_tv
+
+/**
+ * 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.shuttle_p_jl_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.shuttle_p_jl_light_red_nor)
+ this@BusPassengerTrafficLightView.visibility = VISIBLE
+ }
+ TrafficLightEnum.YELLOW -> {
+ bus_p_traffic_light_iv.setBackgroundResource(R.drawable.shuttle_p_jl_light_yellow_nor)
+ this@BusPassengerTrafficLightView.visibility = VISIBLE
+ }
+ TrafficLightEnum.GREEN -> {
+ bus_p_traffic_light_iv.setBackgroundResource(R.drawable.shuttle_p_jl_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.shuttle_p_jl_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.shuttle_p_jl_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.shuttle_p_jl_traffic_light_bg_width).toInt()
+ }
+ }
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/ui/adapter/BusPassengerLineStationsAdapter.java b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/ui/adapter/BusPassengerLineStationsAdapter.java
new file mode 100644
index 0000000000..ed9c65b87f
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/ui/adapter/BusPassengerLineStationsAdapter.java
@@ -0,0 +1,140 @@
+package com.mogo.och.shuttle.passenger.ui.adapter;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.mogo.och.shuttle.passenger.R;
+import com.mogo.och.common.module.utils.BlinkAnimationUtil;
+import com.mogo.och.common.module.wigets.MarqueeTextView;
+import com.mogo.och.data.bean.BusStationBean;
+
+import java.util.List;
+
+import static com.mogo.och.shuttle.passenger.constant.BusPassengerConst.STATION_STATUS_ARRIVING;
+import static com.mogo.och.shuttle.passenger.constant.BusPassengerConst.STATION_STATUS_LEAVING;
+import static com.mogo.och.shuttle.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.shuttle_p_jl_stations_common_item,parent,false);
+ StationViewHolder viewHolder = new StationViewHolder(view);
+ return viewHolder;
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
+ BusStationBean station = mStations.get(position);
+ StationViewHolder viewHolder = (StationViewHolder)holder;
+ viewHolder.stationName.setText(station.getName());
+ BlinkAnimationUtil.clearAnimation(viewHolder.stationCircle);
+ if (position == 0){ //第一个 起点
+ viewHolder.curArrowBg.setVisibility(View.GONE);
+ viewHolder.curArrowBottomBg.setVisibility(View.VISIBLE);
+ Log.d("onBindViewHolder" , "position0 = "+position);
+ viewHolder.stationCircle.setImageResource(R.drawable.shuttle_p_jl_bg_start_tag_bg);
+ if (station.getDrivingStatus() == STATION_STATUS_STOPPED && !station.isLeaving()){//到达未离开
+ viewHolder.stationName.setTextColor(mContext.getResources().getColor(R.color.shuttle_p_jl_clock_17417B));
+ BlinkAnimationUtil.setAnimation(viewHolder.stationCircle);
+ viewHolder.stationName.setEllipsize(TextUtils.TruncateAt.MARQUEE);
+ viewHolder.curArrowBottomBg.setBackgroundColor(mContext.getColor(R.color.shuttle_p_jl_clock_1F82FB));
+ }else {
+ viewHolder.stationName.setTextColor(mContext.getResources().getColor(R.color.shuttle_p_jl_clock_992D3E5F));
+ viewHolder.stationName.setEllipsize(TextUtils.TruncateAt.END);
+ viewHolder.curArrowBottomBg.setBackgroundColor(mContext.getColor(R.color.shuttle_p_jl_clock_A9B6CA));
+ }
+ }else{
+ viewHolder.curArrowBg.setVisibility(View.VISIBLE);
+ viewHolder.curArrowBottomBg.setVisibility(View.VISIBLE);
+ BusStationBean 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.shuttle_p_jl_clock_992D3E5F));
+ viewHolder.curArrowBg.setBackgroundColor(mContext.getColor(R.color.shuttle_p_jl_clock_A9B6CA));
+ viewHolder.curArrowBottomBg.setBackgroundColor(mContext.getColor(R.color.shuttle_p_jl_clock_A9B6CA));
+ viewHolder.stationCircle.setImageResource(R.drawable.shuttle_p_jl_point_gray);
+ viewHolder.stationName.setEllipsize(TextUtils.TruncateAt.END);
+ Log.d("onBindViewHolder" , "position 1 = "+position);
+ } else if (station.getDrivingStatus() == STATION_STATUS_STOPPED && !station.isLeaving()){//刚到站未离开的
+ viewHolder.stationName.setTextColor(mContext.getResources().getColor(R.color.shuttle_p_jl_clock_17417B));
+ viewHolder.curArrowBg.setBackgroundColor(mContext.getColor(R.color.shuttle_p_jl_clock_A9B6CA));
+ viewHolder.curArrowBottomBg.setBackgroundColor(mContext.getColor(R.color.shuttle_p_jl_clock_1F82FB));
+ viewHolder.stationCircle.setImageResource(R.drawable.shuttle_p_jl_arrive_line_green);
+ if (position == mStations.size() - 1){
+ viewHolder.stationCircle.setImageResource(R.drawable.shuttle_p_jl_bg_end_tag_bg);
+ viewHolder.curArrowBottomBg.setVisibility(View.GONE);
+ }
+ Log.d("onBindViewHolder" , "position2 = "+position);
+ 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.shuttle_p_jl_panel_cur_station_tips_color));
+ viewHolder.curArrowBg.setBackgroundColor(mContext.getColor(R.color.shuttle_p_jl_clock_A9B6CA));
+ viewHolder.curArrowBottomBg.setBackgroundColor(mContext.getColor(R.color.shuttle_p_jl_clock_1F82FB));
+ viewHolder.stationCircle.setImageResource(R.drawable.shuttle_p_jl_arrive_line_blue);
+ Log.d("onBindViewHolder" , "position3 = "+position);
+
+ if (position == mStations.size() - 1){
+ viewHolder.curArrowBottomBg.setVisibility(View.GONE);
+ }
+
+ }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.shuttle_p_jl_panel_cur_station_tips_color));
+ viewHolder.curArrowBg.setBackgroundColor(mContext.getColor(R.color.shuttle_p_jl_clock_1F82FB));
+ viewHolder.curArrowBottomBg.setBackgroundColor(mContext.getColor(R.color.shuttle_p_jl_clock_1F82FB));
+ viewHolder.stationCircle.setImageResource(R.drawable.shuttle_p_jl_point_blue);
+ viewHolder.stationName.setEllipsize(TextUtils.TruncateAt.END);
+
+ if (position == mStations.size() - 1){
+ viewHolder.stationCircle.setImageResource(R.drawable.shuttle_p_jl_bg_end_tag_bg);
+ viewHolder.curArrowBottomBg.setVisibility(View.GONE);
+ }
+ Log.d("onBindViewHolder" , "position4 = "+position);
+ }
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ return mStations.size();
+ }
+}
+class StationViewHolder extends RecyclerView.ViewHolder{
+ public MarqueeTextView stationName;
+ public ImageView stationCircle;
+ public ImageView curArrowBg;
+ public ImageView curArrowBottomBg;
+ 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);
+ curArrowBottomBg = itemView.findViewById(R.id.bus_p_cur_arrow_bottom_bg);
+ }
+}
+
+
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/ui/layoutmanager/CenterLayoutManager.java b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/ui/layoutmanager/CenterLayoutManager.java
new file mode 100644
index 0000000000..d7b712d6ea
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/ui/layoutmanager/CenterLayoutManager.java
@@ -0,0 +1,42 @@
+package com.mogo.och.shuttle.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/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/ui/widget/BusPTurnLightView.kt b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/ui/widget/BusPTurnLightView.kt
new file mode 100644
index 0000000000..0016086878
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/jinlv/com/mogo/och/shuttle/passenger/ui/widget/BusPTurnLightView.kt
@@ -0,0 +1,200 @@
+package com.mogo.och.shuttle.passenger.ui.widget
+
+import android.animation.AnimatorSet
+import android.animation.ObjectAnimator
+import android.content.Context
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.view.View
+import android.view.animation.AlphaAnimation
+import android.view.animation.Animation
+import android.widget.ImageView
+import androidx.constraintlayout.widget.ConstraintLayout
+import com.mogo.eagle.core.function.api.datacenter.union.IMoGoTurnLightListener
+import com.mogo.eagle.core.function.call.autopilot.CallerChassisLamplightListenerManager
+import com.mogo.eagle.core.function.call.v2x.CallerTurnLightListenerManager
+import com.mogo.eagle.core.utilcode.util.ThreadUtils
+import com.mogo.och.shuttle.passenger.R
+import com.mogo.och.common.module.manager.light.TurnLightManager
+import kotlinx.android.synthetic.main.shuttle_p_jl_turn_light_status.view.left_nor_image
+import kotlinx.android.synthetic.main.shuttle_p_jl_turn_light_status.view.left_select_image
+import kotlinx.android.synthetic.main.shuttle_p_jl_turn_light_status.view.right_nor_image
+import kotlinx.android.synthetic.main.shuttle_p_jl_turn_light_status.view.right_select_image
+import kotlinx.android.synthetic.main.shuttle_p_jl_turn_light_status.view.turn_light_layout
+
+/**
+ * @author: wangmingjun
+ * @date: 2023/2/13
+ */
+class BusPTurnLightView @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0
+) : ConstraintLayout(context, attrs, defStyleAttr),
+ IMoGoTurnLightListener, TurnLightManager.TurnLightListener {
+
+
+ companion object {
+ private const val TAG = "TurnLightViewStatus"
+ }
+
+ private var isLeftLight: Boolean = false
+ private var isRightLight: Boolean = false
+ private var isDisappear: Boolean = false
+
+ init {
+ LayoutInflater.from(context)
+ .inflate(R.layout.shuttle_p_jl_turn_light_status, this, true)
+ }
+
+ override fun onAttachedToWindow() {
+ super.onAttachedToWindow()
+ CallerTurnLightListenerManager.addListener(TAG,this)
+
+ TurnLightManager.addTurnLightStatusChangeListener(TAG,this)
+ }
+
+ override fun onDetachedFromWindow() {
+ super.onDetachedFromWindow()
+ CallerChassisLamplightListenerManager.removeListener(TAG)
+ CallerTurnLightListenerManager.removeListener(TAG)
+ TurnLightManager.removeTurnLightStatusChangeListener(TAG)
+ }
+
+ override fun hideTurnLightView() {
+ ThreadUtils.runOnUiThread{
+ if (!isDisappear) {
+ isDisappear = true
+ isLeftLight = false
+ isRightLight = false
+ animationDisappear()
+ }
+ }
+ }
+
+ override fun statusChange(newStatus: TurnLightManager.TurnLightStatus) {
+ ThreadUtils.runOnUiThread {
+ setTurnLight(newStatus)
+ }
+ }
+
+ /**
+ * 转向灯动画
+ */
+ private fun setTurnLight(directionLight: TurnLightManager.TurnLightStatus) {
+ if (!isAttachedToWindow) {
+ return
+ }
+ //根据左右进行显示和隐藏,实际要判断每个来的时间和频度
+ when (directionLight) {
+ TurnLightManager.TurnLightStatus.TURN_LIGHT_LEFT -> { //左转向
+ if (!isLeftLight) {
+ isLeftLight = true
+ isRightLight = false
+ isDisappear = false
+ showNormalAnimation()
+ left_select_image.visibility = View.VISIBLE
+ right_select_image.visibility = View.GONE
+ right_select_image.clearAnimation()
+ setAnimation(left_select_image)
+ }
+ }
+ TurnLightManager.TurnLightStatus.TURN_LIGHT_RIGHT -> { //右转向
+ if (!isRightLight) {
+ isRightLight = true
+ isLeftLight = false
+ isDisappear = false
+ showNormalAnimation()
+ left_select_image.visibility = View.GONE
+ right_select_image.visibility = View.VISIBLE
+ left_select_image.clearAnimation()
+ setAnimation(right_select_image)
+ }
+ }
+ TurnLightManager.TurnLightStatus.TURN_LIGHT_NONE -> { //消失
+ if (!isDisappear) {
+ isDisappear = true
+ isLeftLight = false
+ isRightLight = false
+ animationDisappear()
+ }
+ }
+ }
+ }
+
+ //显示背景
+ private fun showNormalAnimation() {
+ val appearAnimation = AlphaAnimation(0f, 1.0f)
+ appearAnimation.duration = 300
+ val appearAnimationImage = AlphaAnimation(0f, 1.0f)
+ appearAnimation.duration = 500
+ turn_light_layout.startAnimation(appearAnimation)
+ left_nor_image.startAnimation(appearAnimationImage)
+ right_nor_image.startAnimation(appearAnimationImage)
+
+ turn_light_layout.visibility = View.VISIBLE
+ left_nor_image.visibility = View.VISIBLE
+ right_nor_image.visibility = View.VISIBLE
+ }
+
+ //消失动画,当转向等数据为空时候
+ private fun animationDisappear() {
+ left_select_image.visibility = View.GONE
+ right_select_image.visibility = View.GONE
+ left_select_image.clearAnimation()
+ right_select_image.clearAnimation()
+
+ left_nor_image.clearAnimation()
+ right_nor_image.clearAnimation()
+ turn_light_layout.clearAnimation()
+
+ val disappearAnimationLeft = AlphaAnimation(1.0f, 0f)
+ disappearAnimationLeft.duration = 300
+
+ val disappearAnimationBg = AlphaAnimation(1.0f, 0f)
+ disappearAnimationBg.duration = 500
+
+ left_nor_image.startAnimation(disappearAnimationLeft)
+ right_nor_image.startAnimation(disappearAnimationLeft)
+ turn_light_layout.startAnimation(disappearAnimationBg)
+
+ disappearAnimationLeft.setAnimationListener(object : Animation.AnimationListener {
+ override fun onAnimationRepeat(p0: Animation?) {
+ }
+
+ override fun onAnimationStart(p0: Animation?) {
+ }
+
+ override fun onAnimationEnd(p0: Animation?) {
+ left_nor_image.visibility = View.GONE
+ right_nor_image.visibility = View.GONE
+ }
+ })
+
+ disappearAnimationBg.setAnimationListener(object : Animation.AnimationListener {
+ override fun onAnimationRepeat(p0: Animation?) {
+ }
+
+ override fun onAnimationStart(p0: Animation?) {
+ }
+
+ override fun onAnimationEnd(p0: Animation?) {
+ turn_light_layout.visibility = View.GONE
+ }
+ })
+ }
+
+ //实现图片闪烁效果
+ private fun setAnimation(imageView: ImageView) {
+ val animationSet = AnimatorSet()
+ val valueAnimator = ObjectAnimator.ofFloat(imageView, "alpha", 0f, 1.0f)
+ val valueAnimatorDisappear = ObjectAnimator.ofFloat(imageView, "alpha", 1.0f, 0f)
+ valueAnimator.duration = 1000
+ valueAnimatorDisappear.duration = 800
+ valueAnimator.repeatCount = -1
+ valueAnimatorDisappear.repeatCount = -1
+ animationSet.playTogether(valueAnimatorDisappear, valueAnimator)
+ animationSet.start()
+ }
+
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/callback/ADASCallback.kt b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/callback/ADASCallback.kt
new file mode 100644
index 0000000000..b5b490e29d
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/callback/ADASCallback.kt
@@ -0,0 +1,10 @@
+package com.mogo.och.shuttle.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/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/callback/AutoPilotStatusCallback.kt b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/callback/AutoPilotStatusCallback.kt
new file mode 100644
index 0000000000..44b2075170
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/callback/AutoPilotStatusCallback.kt
@@ -0,0 +1,14 @@
+package com.mogo.och.shuttle.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/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/callback/DrivingInfoCallback.kt b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/callback/DrivingInfoCallback.kt
new file mode 100644
index 0000000000..88ab043327
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/callback/DrivingInfoCallback.kt
@@ -0,0 +1,19 @@
+package com.mogo.och.shuttle.passenger.callback
+
+import com.mogo.och.data.bean.BusStationBean
+
+/**
+ * @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)
+ fun clearCustomPolyline()
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/constant/M2Const.kt b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/constant/M2Const.kt
new file mode 100644
index 0000000000..fd9097ad64
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/constant/M2Const.kt
@@ -0,0 +1,16 @@
+package com.mogo.och.shuttle.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/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/model/PM2ADASModel.kt b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/model/PM2ADASModel.kt
new file mode 100644
index 0000000000..3994625de7
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/model/PM2ADASModel.kt
@@ -0,0 +1,45 @@
+package com.mogo.och.shuttle.passenger.model
+
+import android.content.Context
+import com.mogo.och.shuttle.passenger.callback.ADASCallback
+import com.mogo.och.data.bean.BusStationBean
+
+/**
+ * @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/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/model/PM2DrivingModel.kt b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/model/PM2DrivingModel.kt
new file mode 100644
index 0000000000..5e0e60eadc
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/model/PM2DrivingModel.kt
@@ -0,0 +1,479 @@
+package com.mogo.och.shuttle.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.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.telematic.IReceivedMsgListener
+import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
+import com.mogo.eagle.core.function.call.telematic.CallerTelematicListenerManager
+import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
+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.GsonUtils
+import com.mogo.eagle.core.utilcode.util.NetworkUtils
+import com.mogo.eagle.core.utilcode.util.StringUtils
+import com.mogo.eagle.core.utilcode.util.ToastUtils
+import com.mogo.och.common.module.manager.socket.cloud.OCHSocketMessageManager.pushAppOperationalMsgBox
+import com.mogo.och.common.module.constant.OchCommonConst
+import com.mogo.och.common.module.manager.autopilot.autopilot.IOchAutopilotStatusListener
+import com.mogo.och.common.module.manager.autopilot.autopilot.OchAutoPilotStatusListenerManager
+import com.mogo.och.common.module.manager.autopilot.location.OchLocationManager
+import com.mogo.och.common.module.network.OchCommonServiceCallback
+import com.mogo.och.common.module.manager.distance.IDistanceListener
+import com.mogo.och.common.module.manager.distance.TrajectoryAndDistanceManager
+import com.mogo.och.common.module.manager.loop.BizLoopManager
+import com.mogo.och.common.module.manager.loop.LoopInfo
+import com.mogo.och.common.module.manager.socket.lan.LanSocketManager
+import com.mogo.och.common.module.manager.socket.lan.bean.AppConnectMsg
+import com.mogo.och.common.module.manager.socket.lan.bean.BaseDPMsg
+import com.mogo.och.common.module.manager.socket.lan.bean.BusinessType
+import com.mogo.och.common.module.manager.socket.lan.bean.DPMsgType
+import com.mogo.och.common.module.manager.socket.lan.bean.TaskDetailsMsg
+import com.mogo.och.common.module.utils.DateTimeUtil
+import com.mogo.och.common.module.voice.VoiceNotice
+import com.mogo.och.common.module.voice.VoiceNotice.showNotice
+import com.mogo.och.data.bean.BusRoutesResult
+import com.mogo.och.data.bean.BusStationBean
+import com.mogo.och.data.bean.BusTransferData
+import com.mogo.och.shuttle.passenger.R
+import com.mogo.och.shuttle.passenger.bean.response.PassengerOperationStatusResponse
+import com.mogo.och.shuttle.passenger.bean.response.PassengerRoutesResponse
+import com.mogo.och.shuttle.passenger.callback.AutoPilotStatusCallback
+import com.mogo.och.shuttle.passenger.callback.DrivingInfoCallback
+import com.mogo.och.shuttle.passenger.constant.BusPassengerConst
+import com.mogo.och.shuttle.passenger.network.PassengerServiceManager
+import io.reactivex.schedulers.Schedulers
+import kotlin.math.abs
+
+/**
+ * @author: wangmingjun
+ * @date: 2023/1/31
+ */
+class PM2DrivingModel private constructor() {
+
+ private var mContext: Context? = null
+
+ private var routesResult: BusRoutesResult? = null
+
+
+ var mStations = mutableListOf()
+ private var mNextStationIndex = 0 // A-B要到达站的index
+ private var isGoingToNextStation = false //是否前往下一站过程中
+
+ private var mDrivingInfoCallback: DrivingInfoCallback? = null //行程信息
+ private var mAutoStatusCallback: AutoPilotStatusCallback? = null //自动驾驶状态
+
+ private var operationStatus: PassengerOperationStatusResponse.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()
+ queryDriverByLocalDriver()
+ queryDriverOperationStatus()
+ BizLoopManager.setLoopFunction(TAG, LoopInfo(2,::queryDriverSiteByCoordinate, scheduler = Schedulers.io()))
+ }
+
+ private fun queryDriverByLocalDriver() {
+ //本地去请求司机端
+ val msg = TaskDetailsMsg("task", BusinessType.shuttle)
+ LanSocketManager.sendMsgToServer(msg)
+ }
+
+ private fun initListener() {
+ //自动驾驶状态监听
+ OchAutoPilotStatusListenerManager.addListener(TAG, mAutoPilotStatusListener)
+
+ // 定位监听
+ OchLocationManager.addGCJ02Listener(TAG, 3, mMapLocationListener)
+
+ //司乘屏通信监听
+ CallerTelematicListenerManager.addListener(TAG, mReceivedMsgListener)
+
+ //网络监听
+ IntentManager.getInstance()
+ .registerIntentListener(ConnectivityManager.CONNECTIVITY_ACTION, mNetWorkIntentListener)
+
+ TrajectoryAndDistanceManager.addDistanceListener(TAG, trajectoryListener)
+
+ }
+
+ fun releaseListener() {
+ //自动驾驶状态监听
+ CallerAutoPilotStatusListenerManager.removeListener(TAG)
+
+ // 定位监听
+ OchLocationManager.removeGCJ02Listener(TAG)
+
+ CallerTelematicListenerManager.removeListener(TAG)
+
+ cleanStation("release")
+
+ TrajectoryAndDistanceManager.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 baseMsg = GsonUtils.fromJson(String(byteArray), BaseDPMsg::class.java)
+ Logger.d(
+ SceneConstant.M_BUS_P + TAG, "onReceivedMsg = " + GsonUtils.toJson(baseMsg)
+ )
+
+ if (baseMsg != null && baseMsg.type == DPMsgType.TYPE_COMMON.type) {
+ val msg = GsonUtils.fromJson(String(byteArray), AppConnectMsg::class.java)
+
+ if (msg != null && msg.isPlay){ //播报
+ speakTTS(msg.msg)
+ }
+
+ if (msg != null && msg.isViewShow) { //消息盒子显示内容
+ pushAppOperationalMsgBox(
+ DateTimeUtil.getCurrentTimeStamp(),msg.msg)
+ }
+ }else if (baseMsg != null && baseMsg.type == DPMsgType.TYPE_TASK_DETAILS.type) {
+ val msg = GsonUtils.fromJson(String(byteArray), TaskDetailsMsg::class.java)
+ Logger.d(
+ SceneConstant.M_BUS_P + TAG, "onReceivedMsg = " + GsonUtils.toJson(msg)
+ )
+ if (msg == null || msg.msg?.isEmpty() == true) {
+ updateLocalOrder()
+ return
+ }
+ val result = GsonUtils.fromJson(msg.msg, BusTransferData::class.java)
+ mDrivingInfoCallback?.changeOperationStatus(result.loginStatus == 1)
+ if (result != null && result.routesResult == null){
+ updateLocalOrder()
+ }
+
+ if (routesResult == null ||
+ (result != null && result.routesResult?.writeVersion!! > routesResult!!.writeVersion)) {
+ routesResult = result.routesResult
+ updatePassengerRouteInfo(routesResult!!)
+ }
+
+ }
+ }
+ }
+ }
+
+ private val trajectoryListener: IDistanceListener = object : IDistanceListener {
+ override fun distanceCallback(distance: Float) {
+ val lastTime = distance / BusPassengerConst.BUS_AVERAGE_SPEED * 3.6 //秒
+ d(SceneConstant.M_BUS_P + TAG, "轨迹排查==lastSumLength = $distance")
+ if (routesResult != null) {
+ for (site in routesResult!!.sites) {
+ if (site.drivingStatus == BusPassengerConst.STATION_STATUS_STOPPED && !site.isLeaving) {
+ return
+ }
+ }
+ }
+ // 小于200m 播报站点介绍
+ if (distance < 200) {
+ val stationNext = mStations[mNextStationIndex]
+ if (!stationNext.isPlayTts) {
+ if (!StringUtils.isEmpty(stationNext.introduction)) {
+ showNotice(stationNext.introduction)
+ stationNext.isPlayTts = true
+ }
+ }
+ }
+ mDrivingInfoCallback?.updateRemainMT(
+ distance.toLong(),
+ lastTime.toLong()
+ )
+ }
+ }
+
+ @RequiresApi(Build.VERSION_CODES.O)
+ private fun speakTTS(msg: String) {
+
+ val mAudioManager = mContext?.getSystemService(Context.AUDIO_SERVICE) as AudioManager
+ val mAudioAttributes = AudioAttributes.Builder()
+ .setUsage(AudioAttributes.USAGE_MEDIA) //设置声音的用途
+ .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) //设置声音的类型
+ .build()
+ val mAudioFocusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) //设置焦点类型
+ .setAudioAttributes(mAudioAttributes) //设置声音属性
+ .setAcceptsDelayedFocusGain(false) //设置接受延迟获取焦点,需要设置OnAudioFocusChangeListener来监听焦点的获取
+ .build()
+ mAudioManager.requestAudioFocus(mAudioFocusRequest) //抢占焦点
+
+ VoiceNotice.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
+ updateSpeed(mogoLocation)
+ }
+ }
+
+ private fun updateSpeed(mogoLocation: MogoLocation) {
+ // km/h
+ val speedKM = (abs(mogoLocation.gnssSpeed) * 3.6f).toInt()
+
+ mDrivingInfoCallback?.updateSpeed(speedKM)
+ }
+
+ private val mAutoPilotStatusListener: IOchAutopilotStatusListener =
+ object : IOchAutopilotStatusListener {
+
+ override fun onAutopilotStatusResponse(state: Int) {
+ super.onAutopilotStatusResponse(state)
+ d(SceneConstant.M_BUS_P+TAG, "onAutopilotStatusResponse ===== $state")
+ if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING != state){
+ //美化模式下且行程中
+ if (FunctionBuildConfig.isDemoMode &&
+ mNextStationIndex>= 0 && mNextStationIndex <= mStations.size - 1
+ && isGoingToNextStation){
+ mAutoStatusCallback?.updateAutoStatus(true)
+ }else{//非美化模式下
+ mAutoStatusCallback?.updateAutoStatus(false)
+ }
+ }else{//自驾状态 2
+ mAutoStatusCallback?.updateAutoStatus(true)
+ }
+ }
+
+ }
+
+ private fun queryDriverOperationDelay() {
+ handler.sendEmptyMessageDelayed(MSG_QUERY_BUS_P_STATION,
+ BusPassengerConst.QUERY_BUS_P_STATION_DELAY
+ )
+ }
+
+ private fun queryDriverOperationStatus() {
+ mContext?.let {
+ PassengerServiceManager.queryDriverOperationStatus(
+ it,
+ object : OchCommonServiceCallback {
+ override fun onSuccess(data: PassengerOperationStatusResponse?) {
+ 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 PassengerOperationStatusResponse.Result
+ }
+
+ 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))
+ }
+ queryDriverByLocalDriver()
+ }
+
+ override fun onFail(code: Int, msg: String) {
+ //延迟3s再次查询
+ queryDriverOperationDelay()
+ }
+ })
+ }
+ }
+
+ fun queryDriverSiteByCoordinate(){
+ mContext?.let {
+ PassengerServiceManager.queryDriverSiteByCoordinate(it,
+ object : OchCommonServiceCallback {
+ override fun onSuccess(data: PassengerRoutesResponse?) {
+
+ 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
+ }
+
+ if (routesResult != null &&
+ routesResult!!.writeVersion < data.result.writeVersion
+ ) {
+ routesResult = data.result
+ }
+
+ if (routesResult == null) {
+ routesResult = data.result
+ }
+ updatePassengerRouteInfo(data.result)
+ }
+
+ override fun onError() {
+ CallerLogger.d(
+ SceneConstant.Companion.M_BUS_P + TAG,
+ "queryDriverSiteByCoordinate = onError ="
+ + ", sn = " + PassengerServiceManager.driverAppSn
+ )
+ queryDriverByLocalDriver()
+ }
+
+ override fun onFail(code: Int, msg: String?) {
+ d(SceneConstant.M_BUS_P+TAG, "queryDriverSiteByCoordinate = %s", msg)
+ if (code == 1003){
+ queryDriverOperationDelay()
+ cleanStation("queryDriverSiteByCoordinate 1003")
+ }
+ if (PassengerServiceManager.driverAppSn.isEmpty()){
+ return
+ }
+ if (code == 1003) {
+ routesResult = null
+ isGoingToNextStation = false
+ return
+ }
+ }
+
+ })
+ }
+ }
+
+ private fun updateLocalOrder(){
+ routesResult = null
+ mNextStationIndex = 0
+ cleanStation("queryDriverSiteByCoordinate")
+ isGoingToNextStation = false
+ mDrivingInfoCallback?.showNoTaskView(true)
+ }
+
+ private fun updatePassengerRouteInfo(result: BusRoutesResult) {
+
+ if (result == null) {
+ updateLocalOrder()
+ return
+ }
+
+ if (routesResult != null && routesResult!!.lineId != result.lineId){
+ d(SceneConstant.M_BUS_P+TAG, "lineId change= clearCustomPolyline")
+ mDrivingInfoCallback?.clearCustomPolyline()
+ }
+
+ d(SceneConstant.M_BUS_P+TAG, "queryDriverSiteByCoordinate= update")
+ routesResult = result
+
+ 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: BusStationBean = stations[i]
+ if (station.drivingStatus == BusPassengerConst.STATION_STATUS_STOPPED
+ && station.isLeaving && i + 1 < stations.size) {
+ mDrivingInfoCallback?.updateStationsInfo(stations as MutableList, i + 1, false)
+ d(SceneConstant.M_BUS_P+TAG,"och-rotting--mNextStationIndex = $mNextStationIndex , i = $i")
+ d(SceneConstant.M_BUS_P+TAG,"och-rotting--start ")
+ isGoingToNextStation = true
+ mNextStationIndex = i + 1
+ val startStation = mStations[i]
+ val endStation = mStations[i + 1]
+ setTrajectoryStation(startStation, endStation, result.lineId)
+ return
+ } else if (station.drivingStatus == BusPassengerConst.STATION_STATUS_STOPPED && !station.isLeaving) {
+ d(SceneConstant.M_BUS_P+TAG,"och-rotting--mNextStationIndex = $mNextStationIndex , i = $i")
+ d(SceneConstant.M_BUS_P+TAG,"och-rotting--arrived ")
+ if (i == stations.size - 1) {
+ cleanStation("updatePassengerRouteInfo最后一个站点")
+ }
+ isGoingToNextStation = false
+ mDrivingInfoCallback?.updateStationsInfo(stations as MutableList, i, true)
+ return
+ }else{
+// d(SceneConstant.M_BUS_P+TAG,"och-rotting--BusStationBean = " + GsonUtils.toJson(station))
+ }
+ }
+ }
+
+ }
+
+ private fun setTrajectoryStation(
+ startStationInfo: BusStationBean,
+ endStationInfo: BusStationBean,
+ lineId: Int
+ ) {
+ val startStation = MogoLocation()
+ startStation.longitude = startStationInfo.gcjLon
+ startStation.latitude = startStationInfo.gcjLat
+ val endStation = MogoLocation()
+ endStation.longitude = endStationInfo.gcjLon
+ endStation.latitude = endStationInfo.gcjLat
+ TrajectoryAndDistanceManager.setStationPoint(startStation, endStation, lineId.toLong())
+ }
+
+ private fun cleanStation(type: String) {
+ d(SceneConstant.M_BUS_P + TAG, "清理站点:$type")
+ TrajectoryAndDistanceManager.setStationPoint(null, null, -1L)
+ }
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/presenter/PM2ADASPresenter.kt b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/presenter/PM2ADASPresenter.kt
new file mode 100644
index 0000000000..4e28ee57de
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/presenter/PM2ADASPresenter.kt
@@ -0,0 +1,41 @@
+package com.mogo.och.shuttle.passenger.presenter
+
+import androidx.lifecycle.LifecycleOwner
+import com.mogo.commons.mvp.Presenter
+import com.mogo.och.shuttle.passenger.callback.ADASCallback
+import com.mogo.och.shuttle.passenger.constant.M2Const.Companion.M2_MAP_STATION_MAKER
+import com.mogo.och.shuttle.passenger.model.PM2ADASModel
+import com.mogo.och.shuttle.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+i,stations[i])
+ }
+
+ }
+
+ override fun removeHDMapStations() {
+ mView?.removeMapMaker(M2_MAP_STATION_MAKER)
+ }
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/presenter/PM2DrivingPresenter.kt b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/presenter/PM2DrivingPresenter.kt
new file mode 100644
index 0000000000..419f50e7ac
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/presenter/PM2DrivingPresenter.kt
@@ -0,0 +1,143 @@
+package com.mogo.och.shuttle.passenger.presenter
+
+import androidx.lifecycle.LifecycleOwner
+import com.amap.api.maps.model.LatLng
+import com.mogo.commons.mvp.Presenter
+import com.mogo.eagle.core.utilcode.util.ThreadUtils
+import com.mogo.och.shuttle.passenger.callback.AutoPilotStatusCallback
+import com.mogo.och.shuttle.passenger.callback.DrivingInfoCallback
+import com.mogo.och.shuttle.passenger.model.PM2ADASModel
+import com.mogo.och.shuttle.passenger.model.PM2DrivingModel
+import com.mogo.och.shuttle.passenger.ui.PM2DrivingInfoFragment
+import com.mogo.och.data.bean.BusStationBean
+
+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) {
+
+ val stationsList = mutableListOf()
+ val stationsListPass = mutableListOf()
+ var startStation: LatLng? = null
+ var endStation: LatLng? = null
+
+ for (i in stations.indices){
+ val station = stations[i]
+ val latLng = LatLng(station.gcjLat,station.gcjLon)
+ if(i==0){
+ startStation = latLng
+ continue
+ }
+ if(i==stations.size-1){
+ endStation = latLng
+ continue
+ }
+ if(station.drivingStatus==1){//行驶信息,0初始值;1已经过;2当前站;3未到站
+ stationsListPass.add(latLng)
+ }else if(station.drivingStatus==2){
+ if(station.isLeaving){
+ stationsListPass.add(latLng)
+ }else{
+ stationsList.add(latLng)
+ }
+ }else{
+ stationsList.add(latLng)
+ }
+
+ }
+
+ ThreadUtils.runOnUiThread {
+ mView?.updateLineStations(stationsList,stationsListPass,startStation,endStation)
+ }
+ PM2ADASModel.INSTANCE.updateHDMapStations(stations)
+ }
+
+ override fun updateStationsInfo(stations: MutableList, i: Int, isArrived: Boolean) {
+ ThreadUtils.runOnUiThread {
+ mView?.updateStationsInfo(stations,i,isArrived)
+ }
+ }
+
+ override fun clearCustomPolyline() {
+ ThreadUtils.runOnUiThread {
+ mView?.clearCustomPolyline()
+ }
+ }
+
+ 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/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/presenter/PM2Presenter.kt b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/presenter/PM2Presenter.kt
new file mode 100644
index 0000000000..450109ef98
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/presenter/PM2Presenter.kt
@@ -0,0 +1,7 @@
+package com.mogo.och.shuttle.passenger.presenter
+
+import com.mogo.commons.mvp.Presenter
+import com.mogo.och.shuttle.passenger.ui.PM2BaseFragment
+
+class PM2Presenter(view: PM2BaseFragment?) :
+ Presenter(view)
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/ui/PM2BaseFragment.kt b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/ui/PM2BaseFragment.kt
new file mode 100644
index 0000000000..38717d851a
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/ui/PM2BaseFragment.kt
@@ -0,0 +1,73 @@
+package com.mogo.och.shuttle.passenger.ui
+
+import com.mogo.commons.mvp.MvpFragment
+import com.mogo.eagle.core.utilcode.util.AppUtils
+import com.mogo.och.shuttle.passenger.R
+import com.mogo.och.shuttle.passenger.presenter.PM2Presenter
+import com.mogo.och.common.module.wigets.media.MediaPlayerFragment
+import kotlinx.android.synthetic.main.shuttle_p_m2_fragment.tv_shuttle_b2_p_version
+
+
+/**
+ * @author: wangmingjun
+ * @date: 2022/4/12
+ */
+class PM2BaseFragment :
+ MvpFragment() {
+
+ private var drivingFragment : PM2DrivingInfoFragment? = null
+ private var hdMapFragment : PM2HPMapFragment? = null
+ private var mediaFragment : MediaPlayerFragment? = null
+
+ override fun getLayoutId(): Int {
+ return R.layout.shuttle_p_m2_fragment
+ }
+
+ override fun getTagName(): String {
+ return TAG
+ }
+
+ override fun initViews() {
+ //横竖屏
+// setScreenDirection()
+ tv_shuttle_b2_p_version.text = "版本:${AppUtils.getAppVersionName()}"
+ //隐藏小地图
+ 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 (mediaFragment == null) mediaFragment = MediaPlayerFragment()
+ childFragmentManager.beginTransaction().add(R.id.video_fragment, mediaFragment!!)
+ .show(mediaFragment!!).commitAllowingStateLoss()
+ }
+
+ override fun createPresenter(): PM2Presenter {
+ return PM2Presenter(this)
+ }
+
+ companion object {
+ public val TAG = PM2BaseFragment::class.java.simpleName
+ }
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/ui/PM2DrivingInfoFragment.kt b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/ui/PM2DrivingInfoFragment.kt
new file mode 100644
index 0000000000..7f36c761cc
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/ui/PM2DrivingInfoFragment.kt
@@ -0,0 +1,301 @@
+package com.mogo.och.shuttle.passenger.ui
+
+import android.graphics.BitmapFactory
+import android.graphics.drawable.AnimationDrawable
+import android.os.Bundle
+import android.view.View
+import androidx.core.content.ContextCompat
+import com.amap.api.maps.model.LatLng
+import com.mogo.commons.AbsMogoApplication
+import com.mogo.commons.mvp.MvpFragment
+import com.mogo.eagle.core.function.hmi.ui.setting.ToggleDebugView
+import com.mogo.eagle.core.function.view.SiteMarkerBean
+import com.mogo.eagle.core.widget.media.video.TextureVideoViewOutlineProvider
+import com.mogo.och.shuttle.passenger.R
+import com.mogo.och.shuttle.passenger.presenter.PM2DrivingPresenter
+import com.mogo.och.common.module.utils.DateTimeUtil.*
+import com.mogo.och.common.module.utils.NumberFormatUtil
+import com.mogo.och.data.bean.BusStationBean
+import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.auto_tv
+import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.clg_distance_left_time
+import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.group_not_select_line
+import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.group_stationinfo
+import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.iv_animal_list
+import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.line_during_tv
+import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.line_name_tv
+import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.overMapView
+import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.speed_tv
+import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.station_name_tv
+import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.tv_arrived_notice
+import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.tv_distance
+import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.tv_left_time
+import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.tv_next_station_title
+
+import me.jessyan.autosize.utils.AutoSizeUtils
+import kotlin.math.ceil
+import kotlin.math.roundToInt
+
+/**
+ * @author: wangmingjun
+ * @date: 2022/4/12
+ */
+class PM2DrivingInfoFragment :
+ MvpFragment() {
+
+ val stationIcon = BitmapFactory.decodeResource(AbsMogoApplication.getApp().resources, R.drawable.shuttle_p_m2_map_staton_icon)
+ val stationPassIcon = BitmapFactory.decodeResource(AbsMogoApplication.getApp().resources, R.drawable.shuttle_p_m2_map_staton_arrived_icon)
+ val startStationIcon = BitmapFactory.decodeResource(AbsMogoApplication.getApp().resources, R.drawable.shuttle_p_m2_map_start_icon)
+ val endStationIcon = BitmapFactory.decodeResource(AbsMogoApplication.getApp().resources, R.drawable.shuttle_p_m2_map_end_icon)
+
+ /**
+ * 改变自动驾驶状态
+ *
+ * @param status 2 - running 1 - enable 2 - disable
+ */
+ override fun getLayoutId(): Int {
+ return R.layout.shuttle_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.shuttle_p_m2_line_name_tv_color))
+ station_name_tv.setTextColor(resources.getColor(R.color.shuttle_p_m2_line_name_tv_color))
+ speed_tv.setVertrial(true)
+ val intArrayOf = intArrayOf(
+ requireContext().resources.getColor(R.color.shuttle_p_m2_color_43cefe),
+ requireContext().resources.getColor(R.color.shuttle_p_m2_color_1466fb)
+ )
+ speed_tv.setmColorList(intArrayOf)
+
+// 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()
+// }
+ }
+
+ override fun initViews(savedInstanceState: Bundle?) {
+ super.initViews(savedInstanceState)
+ overMapView?.let {
+ it.onCreateView(savedInstanceState)
+ val radius = AutoSizeUtils.dp2px(requireContext(), 16f)
+ it.outlineProvider = TextureVideoViewOutlineProvider(radius.toFloat())
+ it.clipToOutline = true
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ overMapView?.let{
+ it.onResume()
+ }
+ }
+
+ override fun onPause() {
+ super.onPause()
+ overMapView?.let{
+ it.onPause()
+ }
+ }
+
+ override fun onDestroyView() {
+ overMapView?.onDestroy()
+ if (mPresenter != null) {
+ mPresenter?.onDestroy(this)
+ }
+ super.onDestroyView()
+ }
+
+ 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
+ }
+
+ fun changeOperationStatus(status:Boolean){
+ if (!status){
+ updateNoOrderUI()
+ }
+ }
+
+ fun showNoTaskView(haveTask: Boolean){
+ setLineInfoView(haveTask)
+ }
+
+ private fun setLineInfoView(isShow: Boolean){
+ if (!isShow){
+ updateNoOrderUI()
+ }
+ }
+
+ private fun updateNoOrderUI() {
+ line_name_tv.text = resources.getString(R.string.shuttle_p_m2_not_select_line_content)
+ updateNoStationView()
+ overMapView?.let {
+ it.clearSiteMarkers()
+ }
+ clearCustomPolyline()
+ }
+
+ fun clearCustomPolyline(){
+ overMapView?.let {
+ it.clearCustomPolyline()
+ }
+ }
+ private fun updateNoStationView(){
+ station_name_tv.setTextColor(resources.getColor(R.color.shuttle_p_m2_next_tv_color))
+ station_name_tv.text = resources.getString(R.string.shuttle_p_m2_empty_tv)
+ tv_distance.text = resources.getString(R.string.shuttle_p_m2_empty_remain_km)
+ tv_left_time.text = resources.getString(R.string.shuttle_p_m2_empty_remain_minute)
+ noLineShow()
+ }
+
+ override fun createPresenter(): PM2DrivingPresenter {
+ return PM2DrivingPresenter(this)
+ }
+
+ fun updateAutoStatus(isAutoPilot: Boolean) {
+ if (isAutoPilot){
+ context?.let { auto_tv.setTextColor(ContextCompat.getColor(it,R.color.shuttle_p_m2_white_color)) }
+ context?.let { auto_tv.background = ContextCompat.getDrawable(it,R.drawable.shuttle_p_m2_auto_button_bg) }
+ }else{
+ context?.let { auto_tv.setTextColor(ContextCompat.getColor(it,R.color.shuttle_p_m2_color_7094ad)) }
+ context?.let { auto_tv.background = ContextCompat.getDrawable(it,R.drawable.shuttle_p_m2_bg_p_m2_auto) }
+ }
+ }
+
+ fun updateLineStations(
+ stations: MutableList,
+ stationsPass: MutableList,
+ startStation: LatLng?,
+ endStation: LatLng?
+ ){
+ overMapView?.let {
+ val stationsList: MutableList = mutableListOf()
+ startStation?.let { start->
+ stationsList.add(SiteMarkerBean(start,startStationIcon,0.5f,0.5f))
+ }
+ for (stationsPass in stationsPass) {
+ stationsList.add(SiteMarkerBean(stationsPass,stationPassIcon,0.5f,0.5f))
+ }
+ for (stationsPass in stations) {
+ stationsList.add(SiteMarkerBean(stationsPass,stationIcon,0.5f,0.5f))
+ }
+ endStation?.let {end->
+ stationsList.add(SiteMarkerBean(end,endStationIcon,0.5f,0.5f))
+ }
+ it.drawSiteMarkers(stationsList)
+ }
+ }
+
+ 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".also { tv_distance.text = it }
+ "${time}分钟".also { tv_left_time.text = it }
+ }
+
+ fun noLineShow(){
+ // 没有线路展示
+ group_not_select_line.visibility = View.VISIBLE
+ // 下一个站点
+ group_stationinfo.visibility = View.GONE
+ // 距离和剩余大概时间
+ clg_distance_left_time.visibility = View.GONE
+ // 到达站点
+ tv_arrived_notice.visibility = View.GONE
+
+ iv_animal_list.visibility = View.GONE
+ }
+ // 有线路正在到站点
+ fun haveLineAndArriveingStation(){
+ group_not_select_line.visibility = View.GONE
+ group_stationinfo.visibility = View.VISIBLE
+ clg_distance_left_time.visibility = View.VISIBLE
+ tv_arrived_notice.visibility = View.GONE
+ iv_animal_list.visibility = View.GONE
+ }
+ // 有线路到达站点
+ private fun haveLineAndArrivedStation(){
+ group_not_select_line.visibility = View.GONE
+ group_stationinfo.visibility = View.VISIBLE
+ clg_distance_left_time.visibility = View.GONE
+ tv_arrived_notice.visibility = View.VISIBLE
+ iv_animal_list.visibility = View.VISIBLE
+ val animationDrawable = iv_animal_list.drawable as AnimationDrawable
+ animationDrawable.start()
+ }
+
+ companion object {
+ private val TAG = PM2DrivingInfoFragment::class.java.simpleName
+ }
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/ui/PM2HPMapFragment.kt b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/ui/PM2HPMapFragment.kt
new file mode 100644
index 0000000000..f0efcd42e8
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/ui/PM2HPMapFragment.kt
@@ -0,0 +1,132 @@
+package com.mogo.och.shuttle.passenger.ui
+
+import android.os.Bundle
+import com.mogo.commons.mvp.MvpFragment
+import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager
+import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d
+import com.mogo.map.overlay.core.Level
+import com.mogo.map.overlay.point.Point
+import com.mogo.map.MapDataWrapper
+import com.mogo.och.shuttle.passenger.R
+import com.mogo.och.shuttle.passenger.constant.M2Const.Companion.TYPE_MARKER_M2_LINE
+import com.mogo.och.shuttle.passenger.presenter.PM2ADASPresenter
+import com.mogo.och.common.module.utils.OCHThreadPoolManager
+import kotlinx.android.synthetic.main.shuttle_p_m2_hpmap_fragment.mapBizView
+
+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.shuttle_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()
+ CallerMapUIServiceManager.getOverlayManager()?.let {
+ it.removeAllLines()
+ it.removeAllPoints()
+ }
+ 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 builder = Point.Options.Builder(
+ TYPE_MARKER_M2_LINE,
+ Level.MAP_MARKER
+ )
+ .setId(uuid)
+ .anchor(0.5f, 0.5f)
+ .set3DMode(true)
+ .isUseGps(true)
+ .controlAngle(true)
+ .icon3DRes(R.raw.star_marker)
+ .longitude(station[0])
+ .latitude(station[1])
+ MapDataWrapper.getCenterLineInfo(
+ station[0], station[1], -1f
+ ) {
+ // 有可能鹰眼map为空没有角度。判空使用后可能造成maker角度跟道路角度不一致 地图未初始化会返回空
+ it?.let{
+ builder.rotate(it.angle.toFloat())
+ }
+ val overlayManager = CallerMapUIServiceManager.getOverlayManager()
+ overlayManager?.showOrUpdatePoint(builder.build())
+ }
+
+ }
+ OCHThreadPoolManager.getsInstance().execute(setMapMarkerRunnable)
+ }
+
+ fun removeMapMaker(
+ uuid: String,
+ ) {
+ //开启线程移除起终点marker设置
+ val removeMapMarkerRunnable = Runnable {
+ d("RemoveMapMaker=" + Thread.currentThread().name, uuid)
+ val overlayManager = CallerMapUIServiceManager.getOverlayManager()
+ overlayManager?.removeAllPointsInOwner(TYPE_MARKER_M2_LINE)
+ }
+ OCHThreadPoolManager.getsInstance().execute(removeMapMarkerRunnable)
+ }
+
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/ui/widget/M2BlueToothView.kt b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/ui/widget/M2BlueToothView.kt
new file mode 100644
index 0000000000..42d43b81db
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/ui/widget/M2BlueToothView.kt
@@ -0,0 +1,36 @@
+package com.mogo.och.shuttle.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.shuttle.passenger.R
+import kotlinx.android.synthetic.main.shuttle_p_m2_view_blue_tooth.view.blueView
+
+/**
+ * 魔戒蓝牙控件
+ * 放置于StatusBar右侧位置
+ */
+class M2BlueToothView @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0
+) : BlueToothView(context, attrs, defStyleAttr),IMoGoDevaToolsListener {
+
+ init {
+ LayoutInflater.from(context).inflate(R.layout.shuttle_p_m2_view_blue_tooth, this, true)
+ }
+
+ override fun mofangStatus(status: Boolean) {
+ ThreadUtils.runOnUiThread {
+ if (status) {
+ blueView.setImageResource(R.drawable.shuttle_p_m2_blue_tooth_close)
+ } else {
+ blueView.setImageResource(R.drawable.shuttle_p_m2_blue_tooth_open)
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/ui/widget/M2PTrafficLightView.kt b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/ui/widget/M2PTrafficLightView.kt
new file mode 100644
index 0000000000..17e0c7e594
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/ui/widget/M2PTrafficLightView.kt
@@ -0,0 +1,181 @@
+package com.mogo.och.shuttle.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.shuttle.passenger.R
+import kotlinx.android.synthetic.main.shuttle_p_m2_traffic_light_view.view.m2_p_traffic_light_bg
+import kotlinx.android.synthetic.main.shuttle_p_m2_traffic_light_view.view.m2_p_traffic_light_iv
+import kotlinx.android.synthetic.main.shuttle_p_m2_traffic_light_view.view.m2_p_traffic_light_time_tv
+
+/**
+ * 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.shuttle_p_m2_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.shuttle_p_m2_light_red_nor)
+ this@M2PTrafficLightView.visibility = VISIBLE
+ }
+ TrafficLightEnum.YELLOW -> {
+ m2_p_traffic_light_iv.setBackgroundResource(R.drawable.shuttle_p_m2_light_yellow_nor)
+ this@M2PTrafficLightView.visibility = VISIBLE
+ }
+ TrafficLightEnum.GREEN -> {
+ m2_p_traffic_light_iv.setBackgroundResource(R.drawable.shuttle_p_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.dp_60).toInt()
+ setLayoutParams(lp)
+ m2_p_traffic_light_time_tv.visibility = VISIBLE
+ m2_p_traffic_light_bg.layoutParams.width =
+ resources.getDimension(R.dimen.dp_60).toInt()
+ }
+ }
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/ui/widget/M2StatusBarView.kt b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/ui/widget/M2StatusBarView.kt
new file mode 100644
index 0000000000..9d837d88bb
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/ui/widget/M2StatusBarView.kt
@@ -0,0 +1,110 @@
+package com.mogo.och.shuttle.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.shuttle.passenger.R
+import kotlinx.android.synthetic.main.shuttle_p_m2_view_status_bar.view.progress
+import kotlinx.android.synthetic.main.shuttle_p_m2_view_status_bar.view.tv_power_cos
+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.shuttle_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/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/ui/widget/M2TurnLightView.kt b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/ui/widget/M2TurnLightView.kt
new file mode 100644
index 0000000000..6b2b1e8e5d
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/java/m2/com/mogo/och/shuttle/passenger/ui/widget/M2TurnLightView.kt
@@ -0,0 +1,200 @@
+package com.mogo.och.shuttle.passenger.ui.widget
+
+import android.animation.AnimatorSet
+import android.animation.ObjectAnimator
+import android.content.Context
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.view.View
+import android.view.animation.AlphaAnimation
+import android.view.animation.Animation
+import android.widget.ImageView
+import androidx.constraintlayout.widget.ConstraintLayout
+import com.mogo.eagle.core.function.api.datacenter.union.IMoGoTurnLightListener
+import com.mogo.eagle.core.function.call.autopilot.CallerChassisLamplightListenerManager
+import com.mogo.eagle.core.function.call.v2x.CallerTurnLightListenerManager
+import com.mogo.eagle.core.utilcode.util.ThreadUtils
+import com.mogo.och.shuttle.passenger.R
+import com.mogo.och.common.module.manager.light.TurnLightManager
+import kotlinx.android.synthetic.main.shuttle_p_jl_turn_light_status.view.left_nor_image
+import kotlinx.android.synthetic.main.shuttle_p_jl_turn_light_status.view.left_select_image
+import kotlinx.android.synthetic.main.shuttle_p_jl_turn_light_status.view.right_nor_image
+import kotlinx.android.synthetic.main.shuttle_p_jl_turn_light_status.view.right_select_image
+import kotlinx.android.synthetic.main.shuttle_p_jl_turn_light_status.view.turn_light_layout
+
+/**
+ * @author: wangmingjun
+ * @date: 2023/2/13
+ */
+class M2TurnLightView @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = 0
+) : ConstraintLayout(context, attrs, defStyleAttr),
+ IMoGoTurnLightListener, TurnLightManager.TurnLightListener {
+
+
+ companion object {
+ private const val TAG = "TurnLightViewStatus"
+ }
+
+ private var isLeftLight: Boolean = false
+ private var isRightLight: Boolean = false
+ private var isDisappear: Boolean = false
+
+ init {
+ LayoutInflater.from(context)
+ .inflate(R.layout.shuttle_p_m2_turn_light_status, this, true)
+ }
+
+ override fun onAttachedToWindow() {
+ super.onAttachedToWindow()
+ CallerTurnLightListenerManager.addListener(TAG,this)
+
+ TurnLightManager.addTurnLightStatusChangeListener(TAG,this)
+ }
+
+ override fun onDetachedFromWindow() {
+ super.onDetachedFromWindow()
+ CallerChassisLamplightListenerManager.removeListener(TAG)
+ CallerTurnLightListenerManager.removeListener(TAG)
+ TurnLightManager.removeTurnLightStatusChangeListener(TAG)
+ }
+
+ override fun hideTurnLightView() {
+ ThreadUtils.runOnUiThread{
+ if (!isDisappear) {
+ isDisappear = true
+ isLeftLight = false
+ isRightLight = false
+ animationDisappear()
+ }
+ }
+ }
+
+ override fun statusChange(newStatus: TurnLightManager.TurnLightStatus) {
+ ThreadUtils.runOnUiThread {
+ setTurnLight(newStatus)
+ }
+ }
+
+ /**
+ * 转向灯动画
+ */
+ private fun setTurnLight(directionLight: TurnLightManager.TurnLightStatus) {
+ if (!isAttachedToWindow) {
+ return
+ }
+ //根据左右进行显示和隐藏,实际要判断每个来的时间和频度
+ when (directionLight) {
+ TurnLightManager.TurnLightStatus.TURN_LIGHT_LEFT -> { //左转向
+ if (!isLeftLight) {
+ isLeftLight = true
+ isRightLight = false
+ isDisappear = false
+ showNormalAnimation()
+ left_select_image.visibility = View.VISIBLE
+ right_select_image.visibility = View.GONE
+ right_select_image.clearAnimation()
+ setAnimation(left_select_image)
+ }
+ }
+ TurnLightManager.TurnLightStatus.TURN_LIGHT_RIGHT -> { //右转向
+ if (!isRightLight) {
+ isRightLight = true
+ isLeftLight = false
+ isDisappear = false
+ showNormalAnimation()
+ left_select_image.visibility = View.GONE
+ right_select_image.visibility = View.VISIBLE
+ left_select_image.clearAnimation()
+ setAnimation(right_select_image)
+ }
+ }
+ TurnLightManager.TurnLightStatus.TURN_LIGHT_NONE -> { //消失
+ if (!isDisappear) {
+ isDisappear = true
+ isLeftLight = false
+ isRightLight = false
+ animationDisappear()
+ }
+ }
+ }
+ }
+
+ //显示背景
+ private fun showNormalAnimation() {
+ val appearAnimation = AlphaAnimation(0f, 1.0f)
+ appearAnimation.duration = 300
+ val appearAnimationImage = AlphaAnimation(0f, 1.0f)
+ appearAnimation.duration = 500
+ turn_light_layout.startAnimation(appearAnimation)
+ left_nor_image.startAnimation(appearAnimationImage)
+ right_nor_image.startAnimation(appearAnimationImage)
+
+ turn_light_layout.visibility = View.VISIBLE
+ left_nor_image.visibility = View.VISIBLE
+ right_nor_image.visibility = View.VISIBLE
+ }
+
+ //消失动画,当转向等数据为空时候
+ private fun animationDisappear() {
+ left_select_image.visibility = View.GONE
+ right_select_image.visibility = View.GONE
+ left_select_image.clearAnimation()
+ right_select_image.clearAnimation()
+
+ left_nor_image.clearAnimation()
+ right_nor_image.clearAnimation()
+ turn_light_layout.clearAnimation()
+
+ val disappearAnimationLeft = AlphaAnimation(1.0f, 0f)
+ disappearAnimationLeft.duration = 300
+
+ val disappearAnimationBg = AlphaAnimation(1.0f, 0f)
+ disappearAnimationBg.duration = 500
+
+ left_nor_image.startAnimation(disappearAnimationLeft)
+ right_nor_image.startAnimation(disappearAnimationLeft)
+ turn_light_layout.startAnimation(disappearAnimationBg)
+
+ disappearAnimationLeft.setAnimationListener(object : Animation.AnimationListener {
+ override fun onAnimationRepeat(p0: Animation?) {
+ }
+
+ override fun onAnimationStart(p0: Animation?) {
+ }
+
+ override fun onAnimationEnd(p0: Animation?) {
+ left_nor_image.visibility = View.GONE
+ right_nor_image.visibility = View.GONE
+ }
+ })
+
+ disappearAnimationBg.setAnimationListener(object : Animation.AnimationListener {
+ override fun onAnimationRepeat(p0: Animation?) {
+ }
+
+ override fun onAnimationStart(p0: Animation?) {
+ }
+
+ override fun onAnimationEnd(p0: Animation?) {
+ turn_light_layout.visibility = View.GONE
+ }
+ })
+ }
+
+ //实现图片闪烁效果
+ private fun setAnimation(imageView: ImageView) {
+ val animationSet = AnimatorSet()
+ val valueAnimator = ObjectAnimator.ofFloat(imageView, "alpha", 0f, 1.0f)
+ val valueAnimatorDisappear = ObjectAnimator.ofFloat(imageView, "alpha", 1.0f, 0f)
+ valueAnimator.duration = 1000
+ valueAnimatorDisappear.duration = 800
+ valueAnimator.repeatCount = -1
+ valueAnimatorDisappear.repeatCount = -1
+ animationSet.playTogether(valueAnimatorDisappear, valueAnimator)
+ animationSet.start()
+ }
+
+}
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/drawable/scanner_qr_code.xml b/OCH/shuttle_weaknet/passenger/src/main/res/drawable/scanner_qr_code.xml
new file mode 100644
index 0000000000..7b205e5aed
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/drawable/scanner_qr_code.xml
@@ -0,0 +1,28 @@
+
+
+
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_arrive_line_blue.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_arrive_line_blue.png
new file mode 100644
index 0000000000..88247c204f
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_arrive_line_blue.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_arrive_line_green.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_arrive_line_green.png
new file mode 100644
index 0000000000..0fd2398cfb
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_arrive_line_green.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_auto_close.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_auto_close.png
new file mode 100644
index 0000000000..bed91e16ee
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_auto_close.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_auto_open.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_auto_open.png
new file mode 100644
index 0000000000..8ecc2ca1e9
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_auto_open.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_bg_arrived_station.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_bg_arrived_station.png
new file mode 100644
index 0000000000..f47f628224
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_bg_arrived_station.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_bg_end_tag_bg.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_bg_end_tag_bg.png
new file mode 100644
index 0000000000..a679341790
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_bg_end_tag_bg.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_bg_start_tag_bg.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_bg_start_tag_bg.png
new file mode 100644
index 0000000000..c0fcf5d0ea
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_bg_start_tag_bg.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_blue_tooth_close.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_blue_tooth_close.png
new file mode 100644
index 0000000000..0c292d2cf3
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_blue_tooth_close.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_blue_tooth_open.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_blue_tooth_open.png
new file mode 100644
index 0000000000..cccf9e10fa
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_blue_tooth_open.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_bus_line_logo.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_bus_line_logo.png
new file mode 100644
index 0000000000..60064ae514
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_bus_line_logo.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_cur_station_arrived_bg.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_cur_station_arrived_bg.png
new file mode 100644
index 0000000000..355af19afc
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_cur_station_arrived_bg.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_cur_station_un_arrived_bg.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_cur_station_un_arrived_bg.png
new file mode 100644
index 0000000000..ea4214cf51
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_cur_station_un_arrived_bg.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_light_green_nor.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_light_green_nor.png
new file mode 100644
index 0000000000..939d5c0214
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_light_green_nor.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_light_red_nor.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_light_red_nor.png
new file mode 100644
index 0000000000..97d774140a
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_light_red_nor.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_light_yellow_nor.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_light_yellow_nor.png
new file mode 100644
index 0000000000..a782062c34
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_light_yellow_nor.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_line_blue.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_line_blue.png
new file mode 100755
index 0000000000..233be50bd5
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_line_blue.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_line_green.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_line_green.png
new file mode 100755
index 0000000000..902cd19c2f
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_line_green.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_map_arrived_point.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_map_arrived_point.png
new file mode 100644
index 0000000000..ac317649b4
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_map_arrived_point.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_map_arrow_arrived.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_map_arrow_arrived.png
new file mode 100644
index 0000000000..fea5cfd033
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_map_arrow_arrived.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_map_arrow_un_arrive.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_map_arrow_un_arrive.png
new file mode 100644
index 0000000000..254662d297
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_map_arrow_un_arrive.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_map_car.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_map_car.png
new file mode 100644
index 0000000000..702f10f265
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_map_car.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_map_end_point.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_map_end_point.png
new file mode 100644
index 0000000000..39262e5ecb
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_map_end_point.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_map_start_point.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_map_start_point.png
new file mode 100644
index 0000000000..b2e4c69ada
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_map_start_point.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_map_unarrived_point.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_map_unarrived_point.png
new file mode 100644
index 0000000000..ec6081f5a3
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_map_unarrived_point.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_no_order_data.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_no_order_data.png
new file mode 100755
index 0000000000..65625ca374
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_no_order_data.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_point_blue.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_point_blue.png
new file mode 100755
index 0000000000..ef08c49f25
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_point_blue.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_point_gray.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_point_gray.png
new file mode 100755
index 0000000000..deec63de9d
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_point_gray.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_right_route_bg.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_right_route_bg.png
new file mode 100644
index 0000000000..5d9bf564af
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_right_route_bg.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_route_bg.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_route_bg.png
new file mode 100644
index 0000000000..5c4f302cc2
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_route_bg.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_speak_arrived_icon_0.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_speak_arrived_icon_0.png
new file mode 100644
index 0000000000..24a13e704e
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_speak_arrived_icon_0.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_speak_arrived_icon_1.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_speak_arrived_icon_1.png
new file mode 100644
index 0000000000..c15a70a3ee
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_speak_arrived_icon_1.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_speak_arrived_icon_2.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_speak_arrived_icon_2.png
new file mode 100644
index 0000000000..8c1c118673
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_speak_arrived_icon_2.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_split_line_bg.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_split_line_bg.png
new file mode 100644
index 0000000000..2f392c64b6
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_split_line_bg.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_status_bar_logo.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_status_bar_logo.png
new file mode 100644
index 0000000000..ffaacad3c6
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_status_bar_logo.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_youzhuan_open.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_youzhuan_open.png
new file mode 100644
index 0000000000..fb728e515e
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_youzhuan_open.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_youzhuan_un_open.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_youzhuan_un_open.png
new file mode 100644
index 0000000000..4de98ca6dd
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_youzhuan_un_open.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_zuozhuan_open.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_zuozhuan_open.png
new file mode 100644
index 0000000000..5762da6053
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_zuozhuan_open.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_zuozhuan_un_open.png b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_zuozhuan_un_open.png
new file mode 100644
index 0000000000..ae29f98f34
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable-nodpi/shuttle_p_jl_zuozhuan_un_open.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_bg_end_station_circle.xml b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_bg_end_station_circle.xml
new file mode 100644
index 0000000000..cb17f7f2c3
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_bg_end_station_circle.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_bg_middle_station_circle.xml b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_bg_middle_station_circle.xml
new file mode 100644
index 0000000000..13b479db48
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_bg_middle_station_circle.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_bg_progress_bar.xml b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_bg_progress_bar.xml
new file mode 100644
index 0000000000..78d4679853
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_bg_progress_bar.xml
@@ -0,0 +1,14 @@
+
+
+ -
+
+
+
+
+
+ -
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_bg_speak_icon_arrived.xml b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_bg_speak_icon_arrived.xml
new file mode 100644
index 0000000000..5590838117
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_bg_speak_icon_arrived.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_bg_start_station_circle.xml b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_bg_start_station_circle.xml
new file mode 100644
index 0000000000..2516df8c8e
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_bg_start_station_circle.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_bg_status_bar.xml b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_bg_status_bar.xml
new file mode 100644
index 0000000000..5b8da3c82c
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_bg_status_bar.xml
@@ -0,0 +1,9 @@
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_bg_traffic_light_background.xml b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_bg_traffic_light_background.xml
new file mode 100644
index 0000000000..4982506777
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_bg_traffic_light_background.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_brakelight_background_daytime.xml b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_brakelight_background_daytime.xml
new file mode 100644
index 0000000000..6409baca2f
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_brakelight_background_daytime.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_dividing_line_bg.xml b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_dividing_line_bg.xml
new file mode 100644
index 0000000000..d5d41809d0
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_dividing_line_bg.xml
@@ -0,0 +1,12 @@
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_panel_cur_station_panel.xml b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_panel_cur_station_panel.xml
new file mode 100644
index 0000000000..9cc2472376
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_panel_cur_station_panel.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_progress_item_round.xml b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_progress_item_round.xml
new file mode 100644
index 0000000000..2d74f8fd54
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/drawable/shuttle_p_jl_progress_item_round.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_base_fragment.xml b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_base_fragment.xml
new file mode 100644
index 0000000000..62f371742b
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_base_fragment.xml
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_map_view.xml b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_map_view.xml
new file mode 100644
index 0000000000..d9fadd6ef5
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_map_view.xml
@@ -0,0 +1,12 @@
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_no_data_common_view.xml b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_no_data_common_view.xml
new file mode 100644
index 0000000000..8240758212
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_no_data_common_view.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_route_fragment.xml b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_route_fragment.xml
new file mode 100644
index 0000000000..2e0ad54917
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_route_fragment.xml
@@ -0,0 +1,278 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_stations_common_item.xml b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_stations_common_item.xml
new file mode 100644
index 0000000000..60d2419315
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_stations_common_item.xml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_traffic_light_view.xml b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_traffic_light_view.xml
new file mode 100644
index 0000000000..41eacc318b
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_traffic_light_view.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_turn_light_status.xml b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_turn_light_status.xml
new file mode 100644
index 0000000000..dfbed02b59
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_turn_light_status.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_view_blue_tooth.xml b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_view_blue_tooth.xml
new file mode 100644
index 0000000000..5bb43874e5
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_view_blue_tooth.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_view_status_bar.xml b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_view_status_bar.xml
new file mode 100644
index 0000000000..cc89490991
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/layout/shuttle_p_jl_view_status_bar.xml
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/values/colors.xml b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/values/colors.xml
new file mode 100644
index 0000000000..6620187e95
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/values/colors.xml
@@ -0,0 +1,24 @@
+
+
+ #5D7199
+ #CCE9EFFC
+ #C7D2E1
+ #203555
+ #FFB327
+ #2D3E5F
+ #276AFE
+ #CDDBF6
+ #2D3E5F
+ #2D3E5F
+
+ #43CEFE
+ #1466FB
+
+ #17417B
+ #6617417B
+ #A9B6CA
+ #1F82FB
+
+ #992D3E5F
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/values/dimens.xml b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/values/dimens.xml
new file mode 100644
index 0000000000..07076fd91d
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/values/dimens.xml
@@ -0,0 +1,29 @@
+
+
+ 750dp
+ 804dp
+ 40dp
+ 48dp
+ 422dp
+
+ 158dp
+ 90dp
+ 45dp
+ 158dp
+ 90dp
+ 45dp
+ 90dp
+ 90dp
+ 3dp
+
+ 34dp
+
+ 38dp
+
+ 90dp
+ 27dp
+
+ 10dp
+ 38dp
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/values/strings.xml b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/values/strings.xml
new file mode 100644
index 0000000000..4170e113bf
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/jinlv/values/strings.xml
@@ -0,0 +1,10 @@
+
+
+ KM/H
+ 您已收车
+ 暂无班次
+ 暂无线路
+ 已到站:
+ 前方到站:
+ 请按秩序下车
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_amap_arrived_road.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_amap_arrived_road.png
new file mode 100644
index 0000000000..f4d80f4cc7
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_amap_arrived_road.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_amap_arriving_road.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_amap_arriving_road.png
new file mode 100644
index 0000000000..a9aae488fb
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_amap_arriving_road.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_amap_custom_corner.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_amap_custom_corner.png
new file mode 100644
index 0000000000..6f0795edaf
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_amap_custom_corner.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_arrived_an_0.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_arrived_an_0.png
new file mode 100644
index 0000000000..62ed7bb92d
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_arrived_an_0.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_arrived_an_1.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_arrived_an_1.png
new file mode 100644
index 0000000000..34f7c0e1f2
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_arrived_an_1.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_arrived_an_2.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_arrived_an_2.png
new file mode 100644
index 0000000000..8b4b214814
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_arrived_an_2.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_auto_button_bg.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_auto_button_bg.png
new file mode 100644
index 0000000000..fb4ddc5279
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_auto_button_bg.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_bg_driving_info_image.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_bg_driving_info_image.png
new file mode 100644
index 0000000000..a829d5b88d
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_bg_driving_info_image.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_blue_tooth_close.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_blue_tooth_close.png
new file mode 100644
index 0000000000..0c292d2cf3
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_blue_tooth_close.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_blue_tooth_open.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_blue_tooth_open.png
new file mode 100644
index 0000000000..cccf9e10fa
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_blue_tooth_open.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_bottom_bg.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_bottom_bg.png
new file mode 100644
index 0000000000..cec9275411
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_bottom_bg.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_card_split.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_card_split.png
new file mode 100644
index 0000000000..5446226be7
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_card_split.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_clock_bg.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_clock_bg.png
new file mode 100644
index 0000000000..a380c3f3b7
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_clock_bg.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_img_drive_bg.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_img_drive_bg.png
new file mode 100644
index 0000000000..7412ab3c90
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_img_drive_bg.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_img_line_bg.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_img_line_bg.png
new file mode 100644
index 0000000000..dd78f6fc9e
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_img_line_bg.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_img_time_bg.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_img_time_bg.png
new file mode 100644
index 0000000000..ba735834b6
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_img_time_bg.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_light_green_nor.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_light_green_nor.png
new file mode 100644
index 0000000000..3135524a79
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_light_green_nor.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_light_red_nor.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_light_red_nor.png
new file mode 100644
index 0000000000..e873c2b85e
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_light_red_nor.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_light_yellow_nor.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_light_yellow_nor.png
new file mode 100644
index 0000000000..8046782601
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_light_yellow_nor.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_lightyellow_nor.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_lightyellow_nor.png
new file mode 100644
index 0000000000..bae01408fd
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_lightyellow_nor.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_line_name.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_line_name.png
new file mode 100644
index 0000000000..beed2f2ad2
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_line_name.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_line_noselect.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_line_noselect.png
new file mode 100644
index 0000000000..bda5e1d105
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_line_noselect.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_line_tile.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_line_tile.png
new file mode 100644
index 0000000000..44070336fa
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_line_tile.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_map_car_icon.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_map_car_icon.png
new file mode 100644
index 0000000000..b9c841cc83
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_map_car_icon.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_map_end_icon.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_map_end_icon.png
new file mode 100644
index 0000000000..39ffc9052f
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_map_end_icon.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_map_start_icon.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_map_start_icon.png
new file mode 100644
index 0000000000..c970699aac
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_map_start_icon.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_map_staton_arrived_icon.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_map_staton_arrived_icon.png
new file mode 100644
index 0000000000..39be18953c
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_map_staton_arrived_icon.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_map_staton_icon.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_map_staton_icon.png
new file mode 100644
index 0000000000..d90c5a2b71
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_map_staton_icon.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_p_video_holder.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_p_video_holder.png
new file mode 100644
index 0000000000..d8c5951e43
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_p_video_holder.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_sky_bg.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_sky_bg.png
new file mode 100644
index 0000000000..7b72c07390
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_sky_bg.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_status_bar_logo.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_status_bar_logo.png
new file mode 100644
index 0000000000..1f6ea692f5
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_status_bar_logo.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_video_bottom_left.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_video_bottom_left.png
new file mode 100644
index 0000000000..5e1fb2c752
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_video_bottom_left.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_video_bottom_right.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_video_bottom_right.png
new file mode 100644
index 0000000000..19ae887a57
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_video_bottom_right.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_video_top_left.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_video_top_left.png
new file mode 100644
index 0000000000..3fb0a40ce3
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_video_top_left.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_video_top_right.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_video_top_right.png
new file mode 100644
index 0000000000..dbc80b2254
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_video_top_right.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_youzhuan_open.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_youzhuan_open.png
new file mode 100644
index 0000000000..bbd2c12d90
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_youzhuan_open.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_youzhuan_un_open.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_youzhuan_un_open.png
new file mode 100644
index 0000000000..7c0dcaabe1
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_youzhuan_un_open.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_zuozhuan_open.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_zuozhuan_open.png
new file mode 100644
index 0000000000..9bbda22cb7
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_zuozhuan_open.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_zuozhuan_un_open.png b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_zuozhuan_un_open.png
new file mode 100644
index 0000000000..7c33fddbd9
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable-nodpi/shuttle_p_m2_zuozhuan_un_open.png differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_dashed_line.xml b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_dashed_line.xml
new file mode 100644
index 0000000000..b26187608d
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_dashed_line.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_driving_arrived_notice.xml b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_driving_arrived_notice.xml
new file mode 100644
index 0000000000..0924ac7748
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_driving_arrived_notice.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_driving_distance_lefttime.xml b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_driving_distance_lefttime.xml
new file mode 100644
index 0000000000..d7e80d7738
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_driving_distance_lefttime.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_driving_info.xml b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_driving_info.xml
new file mode 100644
index 0000000000..38b5f30517
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_driving_info.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_driving_selector.xml b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_driving_selector.xml
new file mode 100644
index 0000000000..21a6524032
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_driving_selector.xml
@@ -0,0 +1,8 @@
+
+
+ -
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_p_m2_arrived_station.xml b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_p_m2_arrived_station.xml
new file mode 100644
index 0000000000..826ca50b64
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_p_m2_arrived_station.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_p_m2_auto.xml b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_p_m2_auto.xml
new file mode 100644
index 0000000000..4189fb8509
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_p_m2_auto.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_p_m2_traffic_light.xml b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_p_m2_traffic_light.xml
new file mode 100644
index 0000000000..5a27da20e0
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_p_m2_traffic_light.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_pnc.xml b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_pnc.xml
new file mode 100644
index 0000000000..38d10320ae
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_bg_pnc.xml
@@ -0,0 +1,5 @@
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_brakelight_background_daytime.xml b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_brakelight_background_daytime.xml
new file mode 100644
index 0000000000..ba372d59df
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_brakelight_background_daytime.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_power_seekbar_style.xml b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_power_seekbar_style.xml
new file mode 100644
index 0000000000..3ac0c761ba
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/m2/drawable/shuttle_p_m2_power_seekbar_style.xml
@@ -0,0 +1,26 @@
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_driving_info_fragment.xml b/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_driving_info_fragment.xml
new file mode 100644
index 0000000000..8f5c360ae6
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_driving_info_fragment.xml
@@ -0,0 +1,379 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_fragment.xml b/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_fragment.xml
new file mode 100644
index 0000000000..cb409b7a2b
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_fragment.xml
@@ -0,0 +1,167 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_hpmap_fragment.xml b/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_hpmap_fragment.xml
new file mode 100644
index 0000000000..5c9a902baa
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_hpmap_fragment.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_traffic_light_view.xml b/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_traffic_light_view.xml
new file mode 100644
index 0000000000..83567814d2
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_traffic_light_view.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_turn_light_status.xml b/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_turn_light_status.xml
new file mode 100644
index 0000000000..a1699ac360
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_turn_light_status.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_video_fragment.xml b/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_video_fragment.xml
new file mode 100644
index 0000000000..66e95d9087
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_video_fragment.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_video_view.xml b/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_video_view.xml
new file mode 100644
index 0000000000..9d75478ee1
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_video_view.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_view_blue_tooth.xml b/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_view_blue_tooth.xml
new file mode 100644
index 0000000000..61448bf16d
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_view_blue_tooth.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_view_status_bar.xml b/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_view_status_bar.xml
new file mode 100644
index 0000000000..d666101542
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/m2/layout/shuttle_p_m2_view_status_bar.xml
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/raw/star_marker.nt3d b/OCH/shuttle_weaknet/passenger/src/main/res/m2/raw/star_marker.nt3d
new file mode 100644
index 0000000000..94440d9eb6
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/raw/star_marker.nt3d differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/raw/station_marker.nt3d b/OCH/shuttle_weaknet/passenger/src/main/res/m2/raw/station_marker.nt3d
new file mode 100644
index 0000000000..04c83821aa
Binary files /dev/null and b/OCH/shuttle_weaknet/passenger/src/main/res/m2/raw/station_marker.nt3d differ
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/values/colors.xml b/OCH/shuttle_weaknet/passenger/src/main/res/m2/values/colors.xml
new file mode 100644
index 0000000000..b0196c0ce9
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/m2/values/colors.xml
@@ -0,0 +1,27 @@
+
+
+ #FFFFFF
+ #0B1E38
+ #BBDAFB
+ #0B1E38
+ #5D7199
+ #A5D8FF
+ #1B2546
+ #23355D
+ #8895B7
+
+
+ #C8EFFF
+ #203555
+ #17417B
+ #2D3E5F
+ #34A61F
+ #AEEDB8
+ #43CEFE
+ #1466FB
+ #7094AD
+ #80FFFFFF
+
+ #99AFC9E7
+ #6617417B
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/values/dimens.xml b/OCH/shuttle_weaknet/passenger/src/main/res/m2/values/dimens.xml
new file mode 100644
index 0000000000..55344e5192
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/m2/values/dimens.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/main/res/m2/values/strings.xml b/OCH/shuttle_weaknet/passenger/src/main/res/m2/values/strings.xml
new file mode 100644
index 0000000000..d2faf78c18
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/main/res/m2/values/strings.xml
@@ -0,0 +1,14 @@
+
+
+ KM/H
+ m2_map_style.data
+ m2_map_style_extra.data
+ AUTO
+ 已到站
+ 暂无站点
+ 前方到站
+ —公里
+ —分钟
+ 请按秩序下车
+ 暂无路线
+
\ No newline at end of file
diff --git a/OCH/shuttle_weaknet/passenger/src/test/java/passenger/ExampleUnitTest.java b/OCH/shuttle_weaknet/passenger/src/test/java/passenger/ExampleUnitTest.java
new file mode 100644
index 0000000000..d940b2948f
--- /dev/null
+++ b/OCH/shuttle_weaknet/passenger/src/test/java/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/settings.gradle b/settings.gradle
index 5b164b1816..d902e055b8 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -81,4 +81,8 @@ include ':OCH:charter:passenger'
include ':OCH:shuttle:driver'
include ':OCH:shuttle:passenger'
+include ':OCH:shuttle_weaknet:driver'
+include ':OCH:shuttle_weaknet:passenger'
+
+
include ':core:function-impl:mogo-core-function-patch'