[清扫车 Sweepers 1.0.0] init Sweepers
@@ -3,4 +3,5 @@
|
||||
2. mogo-och-bus-passenger:Bus乘客端(BusPassenger)
|
||||
3. mogo-och-taxi:Taxi司机端(Taxi)
|
||||
4. mogo-och-taxi-passenger:Taxi乘客端(TaxiPassenger)
|
||||
5. mogo-och-noop:空实现,用于独立鹰眼打包
|
||||
5. mogo-och-noop:空实现,用于独立鹰眼打包
|
||||
6. mogo-och-sweepers: 清扫车(Sweepers)
|
||||
1
OCH/mogo-och-sweepers/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
75
OCH/mogo-och-sweepers/build.gradle
Normal file
@@ -0,0 +1,75 @@
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'com.alibaba.arouter'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.android.compileSdkVersion
|
||||
// buildToolsVersion rootProject.ext.android.buildToolsVersion
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.ext.android.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.android.targetSdkVersion
|
||||
versionCode Integer.valueOf(VERSION_CODE)
|
||||
versionName getValueFromRootProperties("${project.name.replace("-", "_").toUpperCase()}_VERSION")
|
||||
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles "consumer-rules.pro"
|
||||
|
||||
javaCompileOptions {
|
||||
annotationProcessorOptions {
|
||||
arguments = [AROUTER_MODULE_NAME: project.getName()]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
debug {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||
implementation rootProject.ext.dependencies.kotlinstdlibjdk7
|
||||
implementation rootProject.ext.dependencies.androidxappcompat
|
||||
implementation rootProject.ext.dependencies.arouter
|
||||
annotationProcessor rootProject.ext.dependencies.aroutercompiler
|
||||
implementation rootProject.ext.dependencies.androidxconstraintlayout
|
||||
implementation rootProject.ext.dependencies.amapnavi3dmap
|
||||
|
||||
implementation rootProject.ext.dependencies.rxjava
|
||||
implementation rootProject.ext.dependencies.rxandroid
|
||||
|
||||
implementation project(":OCH:mogo-och-common-module")
|
||||
|
||||
implementation rootProject.ext.dependencies.androidxrecyclerview
|
||||
if (Boolean.valueOf(USE_MAVEN_PACKAGE)) {
|
||||
implementation rootProject.ext.dependencies.mogoutils
|
||||
implementation rootProject.ext.dependencies.mogocommons
|
||||
implementation rootProject.ext.dependencies.modulecommon
|
||||
implementation rootProject.ext.dependencies.mogo_core_data
|
||||
implementation rootProject.ext.dependencies.mogo_core_function_call
|
||||
implementation rootProject.ext.dependencies.mogo_core_function_hmi
|
||||
}else {
|
||||
implementation project(":core:mogo-core-utils")
|
||||
implementation project(":foudations:mogo-commons")
|
||||
implementation project(':modules:mogo-module-common')
|
||||
implementation project(':core:mogo-core-data')
|
||||
implementation project(':core:mogo-core-function-call')
|
||||
implementation project(':core:function-impl:mogo-core-function-hmi')
|
||||
}
|
||||
}
|
||||
|
||||
apply from: new File(rootProject.rootDir, "gradle/upload.gradle").toString()
|
||||
3
OCH/mogo-och-sweepers/gradle.properties
Normal file
@@ -0,0 +1,3 @@
|
||||
GROUP=com.mogo.och
|
||||
POM_ARTIFACT_ID=och-sweepers
|
||||
VERSION_CODE=1
|
||||
21
OCH/mogo-och-sweepers/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.mogo.och.sweepers
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("com.mogo.och.sweepers", appContext.packageName)
|
||||
}
|
||||
}
|
||||
20
OCH/mogo-och-sweepers/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.mogo.och.sweepers">
|
||||
|
||||
<application>
|
||||
<!--这里是为了测试增加的广播-->
|
||||
<receiver android:name=".receiver.TestSweepersBroadcastReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="com.bus.test_control" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<activity android:name=".ui.SweepersSwitchLineActivity"
|
||||
android:theme="@style/SwitchLineDialogStyle"
|
||||
android:launchMode="singleTask"
|
||||
android:screenOrientation="landscape" />/>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.mogo.och.sweepers;
|
||||
|
||||
import androidx.annotation.IdRes;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import com.mogo.eagle.core.function.api.base.IMoGoFunctionProvider;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2021/1/15
|
||||
*
|
||||
* 网约车抽象接口
|
||||
*/
|
||||
interface IMogoOCH extends IMoGoFunctionProvider {
|
||||
|
||||
/**
|
||||
* 初始化网约车容器
|
||||
*
|
||||
* @param activity
|
||||
* @param containerId 容器ID
|
||||
*/
|
||||
void createCoverage(FragmentActivity activity, @IdRes int containerId);
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package com.mogo.och.sweepers;
|
||||
|
||||
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import com.alibaba.android.arouter.facade.annotation.Route;
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
|
||||
import com.mogo.map.MogoMapUIController;
|
||||
import com.mogo.module.common.MogoApisHandler;
|
||||
import com.mogo.och.sweepers.constant.SweepersConst;
|
||||
import com.mogo.och.sweepers.fragment.SweepersFragment;
|
||||
import com.mogo.service.statusmanager.IMogoStatusChangedListener;
|
||||
import com.mogo.service.statusmanager.StatusDescriptor;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* 清扫车业务实现入口
|
||||
*
|
||||
* @author tongchenfei
|
||||
*/
|
||||
@Route(path = SweepersConst.PATH)
|
||||
public class SweepersProvider implements IMogoOCH {
|
||||
|
||||
private static final String TAG = "SweepersProvider";
|
||||
|
||||
private SweepersFragment sweepersFragment;
|
||||
private int containerId;
|
||||
private FragmentActivity activity;
|
||||
|
||||
/**
|
||||
* 进入鹰眼模式,设置手势缩放地图失效
|
||||
*/
|
||||
private void stepIntoVrMode(){
|
||||
CallerLogger.INSTANCE.d( M_BUS + TAG, "进入vr模式" );
|
||||
MogoMapUIController.getInstance()
|
||||
.stepInVrMode(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Context context) {
|
||||
MogoApisHandler.getInstance().getApis().getStatusManagerApi().registerStatusChangedListener("OchSweepers"
|
||||
, StatusDescriptor.VR_MODE, statusChangedListener);
|
||||
}
|
||||
|
||||
private void showFragment() {
|
||||
if (sweepersFragment == null) {
|
||||
CallerLogger.INSTANCE.d(TAG, "准备add fragment======");
|
||||
sweepersFragment = new SweepersFragment();
|
||||
activity.getSupportFragmentManager().beginTransaction().add(containerId, sweepersFragment).commitAllowingStateLoss();
|
||||
return;
|
||||
}
|
||||
CallerLogger.INSTANCE.d(TAG, "准备show fragment");
|
||||
activity.getSupportFragmentManager().beginTransaction().show(sweepersFragment).commitAllowingStateLoss();
|
||||
}
|
||||
|
||||
private void hideFragment() {
|
||||
if (sweepersFragment != null) {
|
||||
CallerLogger.INSTANCE.d(TAG, "准备hide fragment");
|
||||
activity.getSupportFragmentManager().beginTransaction().hide(sweepersFragment).commitAllowingStateLoss();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final IMogoStatusChangedListener statusChangedListener = (descriptor, isTrue) -> {
|
||||
if (descriptor == StatusDescriptor.VR_MODE) {
|
||||
// 进入vr模式默认显示网约车小巴fragment
|
||||
if (isTrue) {
|
||||
showFragment();
|
||||
} else {
|
||||
hideFragment();
|
||||
}
|
||||
} else if (MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode()) {
|
||||
// topView进行展示时推出网约车界面,但是不隐藏整个fragment
|
||||
if (sweepersFragment != null && isTrue) {
|
||||
sweepersFragment.hideOchSweepers();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void createCoverage(FragmentActivity activity, int containerId) {
|
||||
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFunctionName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Fragment createCoverage(@Nullable FragmentActivity fragmentActivity, @Nullable Integer integer) {
|
||||
|
||||
this.containerId = integer;
|
||||
this.activity = fragmentActivity;
|
||||
|
||||
// UiThreadHandler.postDelayed(this::stepIntoVrMode, 5_000L );
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
//若不调用finish, 设置中打开关闭UITouch,会造成och fragment 重叠
|
||||
if (activity == null) return;
|
||||
activity.finish();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.mogo.och.sweepers.bean;
|
||||
|
||||
import com.mogo.och.sweepers.constant.SweepersConst;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Created on 2021/9/16
|
||||
*
|
||||
* 上传车机心跳信息请求数据
|
||||
*/
|
||||
public class CarHeartbeatReqBean {
|
||||
public String sn;
|
||||
public double lon; //经度
|
||||
public double lat; //纬度
|
||||
public String msgId; //心跳信息唯一标识
|
||||
public int interval; //上报间隔,单位秒,非必传,默认60秒
|
||||
|
||||
public CarHeartbeatReqBean(String sn, double lon, double lat) {
|
||||
this.sn = sn;
|
||||
this.lon = lon;
|
||||
this.lat = lat;
|
||||
this.msgId = UUID.randomUUID().toString();
|
||||
this.interval = (int) (SweepersConst.LOOP_PERIOD_60S / 1000);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.mogo.och.sweepers.bean;
|
||||
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
|
||||
import com.mogo.commons.network.Utils;
|
||||
|
||||
/**
|
||||
* 查询下车乘客请求参数
|
||||
*
|
||||
* @author tongchenfei
|
||||
*/
|
||||
public class QueryLeaveAwayPassengersRequest {
|
||||
private String sn;
|
||||
private int seq; //站点在线路中的序号
|
||||
private int siteId; //站点id
|
||||
|
||||
public QueryLeaveAwayPassengersRequest(int seq, int siteId) {
|
||||
this.sn = MoGoAiCloudClientConfig.getInstance().getSn();
|
||||
this.seq = seq;
|
||||
this.siteId = siteId;
|
||||
}
|
||||
|
||||
public void setSeq(int seq) {
|
||||
this.seq = seq;
|
||||
}
|
||||
|
||||
public void setSiteId(int siteId) {
|
||||
this.siteId = siteId;
|
||||
}
|
||||
|
||||
public int getSeq() {
|
||||
return seq;
|
||||
}
|
||||
|
||||
public int getSiteId() {
|
||||
return siteId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.mogo.och.sweepers.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<Double> startSitePoint;
|
||||
public String startSiteAddr;
|
||||
public int endSiteId;
|
||||
public List<Double> endSitePoint;
|
||||
public String carNumber;
|
||||
public long createTime;
|
||||
public long startTime;
|
||||
public List< Double > startSiteGcjPoint;
|
||||
public List< Double > endSiteGcjPoint;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.mogo.och.sweepers.bean;
|
||||
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
|
||||
import com.mogo.commons.network.Utils;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2021/3/22
|
||||
*
|
||||
* 小巴车运营状态请求参数
|
||||
*/
|
||||
class SweepersOperationStatusRequest {
|
||||
|
||||
private String sn;
|
||||
private double lat;
|
||||
private double lon;
|
||||
public SweepersOperationStatusRequest(double lon, double lat) {
|
||||
this.sn = MoGoAiCloudClientConfig.getInstance().getSn();
|
||||
this.lat = lat;
|
||||
this.lon = lon;
|
||||
}
|
||||
public void setLat(double lat) {
|
||||
this.lat = lat;
|
||||
}
|
||||
|
||||
public void setLon(double lon) {
|
||||
this.lon = lon;
|
||||
}
|
||||
|
||||
public String getSn() {
|
||||
return sn;
|
||||
}
|
||||
|
||||
public double getLat() {
|
||||
return lat;
|
||||
}
|
||||
|
||||
public double getLon() {
|
||||
return lon;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.mogo.och.sweepers.bean;
|
||||
|
||||
import com.mogo.eagle.core.data.BaseData;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2021/3/22
|
||||
*
|
||||
* 小巴车运营状态返回参数
|
||||
*/
|
||||
public class SweepersOperationStatusResponse extends BaseData {
|
||||
|
||||
public Result data;
|
||||
|
||||
public static class Result {
|
||||
|
||||
public int serviceStatus;//0:已收车,1:已出车
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.mogo.och.sweepers.bean;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2021/3/23
|
||||
* <p>
|
||||
* 小巴订单
|
||||
*/
|
||||
public class SweepersOrderBean {
|
||||
|
||||
/**
|
||||
* 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 +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.mogo.och.sweepers.bean;
|
||||
|
||||
import com.mogo.eagle.core.data.BaseData;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2021/10/19
|
||||
*/
|
||||
public class SweepersOrdersResponse extends BaseData {
|
||||
public Result data;
|
||||
public static class Result{
|
||||
public List<SweepersOrderBean> orders;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BusOrdersResponse{" +
|
||||
"data=" + data +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.mogo.och.sweepers.bean;
|
||||
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2021/3/22
|
||||
*
|
||||
* 根据车机行驶线路站点信息
|
||||
*/
|
||||
public class SweepersQueryLineStationsRequest {
|
||||
|
||||
private String sn;
|
||||
private double lat;
|
||||
private double lon;
|
||||
private boolean markDrivingStatus; // 默认false;true:是否需要返回站点的行驶状态,对应返回的drivingStatus
|
||||
// 0 - 关闭、1 - 启动
|
||||
// public String status;
|
||||
public SweepersQueryLineStationsRequest(double lon, double lat, boolean markDrivingStatus) {
|
||||
this.sn = MoGoAiCloudClientConfig.getInstance().getSn();
|
||||
this.lat = lat;
|
||||
this.lon = lon;
|
||||
this.markDrivingStatus = markDrivingStatus;
|
||||
}
|
||||
|
||||
public boolean isMarkDrivingStatus() {
|
||||
return markDrivingStatus;
|
||||
}
|
||||
|
||||
public void setMarkDrivingStatus(boolean markDrivingStatus) {
|
||||
this.markDrivingStatus = markDrivingStatus;
|
||||
}
|
||||
|
||||
public void setLat(double lat) {
|
||||
this.lat = lat;
|
||||
}
|
||||
|
||||
public void setLon(double lon) {
|
||||
this.lon = lon;
|
||||
}
|
||||
|
||||
public String getSn() {
|
||||
return sn;
|
||||
}
|
||||
|
||||
public double getLat() {
|
||||
return lat;
|
||||
}
|
||||
|
||||
public double getLon() {
|
||||
return lon;
|
||||
}
|
||||
// public BusOperationStatusRequest shutdown() {
|
||||
// status = "0";
|
||||
// return this;
|
||||
// }
|
||||
//
|
||||
// public BusOperationStatusRequest launch() {
|
||||
// status = "1";
|
||||
// return this;
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.mogo.och.sweepers.bean;
|
||||
|
||||
import com.mogo.eagle.core.data.BaseData;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2022/2/9
|
||||
*/
|
||||
public class SweepersQueryLinesResponse extends BaseData {
|
||||
public List<Result> data;
|
||||
|
||||
public static class Result {
|
||||
|
||||
public int lineId;//线路id
|
||||
public String name;//线路名字
|
||||
public int choose; // 1:绑定 2:未被绑定
|
||||
public String startSiteName;//始发站名称
|
||||
public String endSiteName;//终点名称
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.mogo.och.sweepers.bean;
|
||||
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
|
||||
import com.mogo.commons.network.Utils;
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2021/10/18
|
||||
*/
|
||||
public class SweepersResetDrivingLineRequest {
|
||||
public String sn;
|
||||
public int lineId; //切换到的线路id
|
||||
|
||||
public SweepersResetDrivingLineRequest(int lineId) {
|
||||
sn = MoGoAiCloudClientConfig.getInstance().getSn();
|
||||
this.lineId = lineId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.mogo.och.sweepers.bean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by pangfan on 2021/8/19
|
||||
*
|
||||
* 订单状态更新请求数据结构
|
||||
*/
|
||||
public class SweepersRoutePlanningUpdateReqBean {
|
||||
public String sn;
|
||||
public int lineId;
|
||||
public int startSiteId;
|
||||
public int endSiteId;
|
||||
public List<Result> points;
|
||||
|
||||
public static class Result {
|
||||
public Double latitude;
|
||||
public Double longitude;
|
||||
}
|
||||
|
||||
public SweepersRoutePlanningUpdateReqBean(String sn, int lineId, int startSiteId
|
||||
, int endSiteId, List<Result> points) {
|
||||
this.sn = sn;
|
||||
this.lineId = lineId;
|
||||
this.startSiteId = startSiteId;
|
||||
this.endSiteId = endSiteId;
|
||||
this.points = points;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.mogo.och.sweepers.bean;
|
||||
|
||||
import com.mogo.eagle.core.data.BaseData;
|
||||
|
||||
/**
|
||||
* 网约车小巴路线接口请求响应结果
|
||||
*
|
||||
* @author tongchenfei
|
||||
*/
|
||||
public class SweepersRoutesResponse extends BaseData {
|
||||
private SweepersRoutesResult data;
|
||||
|
||||
public SweepersRoutesResult getResult() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setResult(SweepersRoutesResult data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BusRoutesResponse{" +
|
||||
"data=" + data +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.mogo.och.sweepers.bean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 网约车小巴路线接口返回接口数据封装
|
||||
*
|
||||
* @author tongchenfei
|
||||
*/
|
||||
public class SweepersRoutesResult {
|
||||
private List<SweepersStationBean> sites;
|
||||
private int lineId;
|
||||
private String name;
|
||||
private int lineType; //线路类型,0:环形
|
||||
private String description;
|
||||
private int status;
|
||||
|
||||
//线路轨迹相关字段
|
||||
public String csvFileUrl = ""; //轨迹文件下载的cos url,默认“”
|
||||
public String csvFileMd5 = ""; //轨迹文件md5,默认“”
|
||||
public String txtFileUrl = ""; //打点文件下载的cos url,默认“”
|
||||
public String txtFileMd5 = ""; //轨迹文件md5,默认“”
|
||||
public long contrailSaveTime; //上传轨迹完成时间戳ms:用于MEC本地手动导入轨迹验证时不会被云端轨迹覆盖
|
||||
public String carModel = ""; //[optional] 车型号(如红旗H9),默认“”,暂不加入校验逻辑、用于人工排查问题
|
||||
public String csvFileUrlDPQP = ""; //轨迹文件下载的cos url,默认“”
|
||||
public String csvFileMd5DPQP = ""; //轨迹文件md5,默认“”
|
||||
public String txtFileUrlDPQP = ""; //打点文件下载的cos url,默认“”
|
||||
public String txtFileMd5DPQP = ""; //轨迹文件md5,默认“”
|
||||
public long contrailSaveTimeDPQP; //上传轨迹完成时间戳ms:用于MEC本地手动导入轨迹验证时不会被云端轨迹覆盖
|
||||
|
||||
public int getLineId() {
|
||||
return lineId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public List<SweepersStationBean> getSites() {
|
||||
return sites;
|
||||
}
|
||||
|
||||
public void setSite(List<SweepersStationBean> site) {
|
||||
this.sites = sites;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BusRoutesResult{" +
|
||||
"sites=" + sites +
|
||||
", lineId=" + lineId +
|
||||
", name='" + name + '\'' +
|
||||
", lineType=" + lineType +
|
||||
", description='" + description + '\'' +
|
||||
", status=" + status +
|
||||
", csvFileUrl='" + csvFileUrl + '\'' +
|
||||
", csvFileMd5='" + csvFileMd5 + '\'' +
|
||||
", txtFileUrl='" + txtFileUrl + '\'' +
|
||||
", txtFileMd5='" + txtFileMd5 + '\'' +
|
||||
", contrailSaveTime=" + contrailSaveTime +
|
||||
", carModel='" + carModel + '\'' +
|
||||
", csvFileUrlDPQP='" + csvFileUrlDPQP + '\'' +
|
||||
", csvFileMd5DPQP='" + csvFileMd5DPQP + '\'' +
|
||||
", txtFileUrlDPQP='" + txtFileUrlDPQP + '\'' +
|
||||
", txtFileMd5DPQP='" + txtFileMd5DPQP + '\'' +
|
||||
", contrailSaveTimeDPQP=" + contrailSaveTimeDPQP +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
package com.mogo.och.sweepers.bean;
|
||||
|
||||
/**
|
||||
* 单个网约车小巴车站信息
|
||||
*
|
||||
* @author tongchenfei
|
||||
*/
|
||||
public class SweepersStationBean {
|
||||
// private int lineId;
|
||||
// private int siteId;
|
||||
// private String siteName;
|
||||
// private String cityCode;
|
||||
// private String areaCode;
|
||||
// private String areaName;
|
||||
// private double lat;
|
||||
// private double lon;
|
||||
// private String siteDesc;
|
||||
// private int siteState;
|
||||
// private int isCurrentSite;// @see OchBusConst 是否是当前站 1:是 2:下一站 0:普通站
|
||||
// private int siteColor;
|
||||
// private String peoples;
|
||||
// private int ifStop; // 是否需要停靠、1需要、0不需要
|
||||
|
||||
|
||||
private String name;
|
||||
private String description;
|
||||
private String cityCode;
|
||||
private double lon; //高精坐标
|
||||
private double lat; //高精坐标
|
||||
private int businessType; //站点类型,9:taxi,10:bus
|
||||
private double gcjLon; //高德
|
||||
private double gcjLat; //高德
|
||||
private int status;
|
||||
private int siteId;
|
||||
private int seq;
|
||||
private int drivingStatus;//行驶信息,0初始值;1已经过;2当前站;3未到站
|
||||
private int ifStop = 1; // 是否需要停靠、1需要、0不需要 // TODO: 2021/10/19 原来站点里有设计是否需要停靠字段,现设计暂无,默认都需要停靠
|
||||
private boolean leaving;
|
||||
|
||||
public double getGcjLon() {
|
||||
return gcjLon;
|
||||
}
|
||||
|
||||
public double getGcjLat() {
|
||||
return gcjLat;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public void setCityCode(String cityCode) {
|
||||
this.cityCode = cityCode;
|
||||
}
|
||||
|
||||
public void setLon(double lon) {
|
||||
this.lon = lon;
|
||||
}
|
||||
|
||||
public void setLat(double lat) {
|
||||
this.lat = lat;
|
||||
}
|
||||
|
||||
public void setBusinessType(int businessType) {
|
||||
this.businessType = businessType;
|
||||
}
|
||||
|
||||
public void setStatus(int status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public void setSiteId(int siteId) {
|
||||
this.siteId = siteId;
|
||||
}
|
||||
|
||||
public void setSeq(int seq) {
|
||||
this.seq = seq;
|
||||
}
|
||||
|
||||
public void setDrivingStatus(int drivingStatus) {
|
||||
this.drivingStatus = drivingStatus;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public String getCityCode() {
|
||||
return cityCode;
|
||||
}
|
||||
|
||||
|
||||
public int getBusinessType() {
|
||||
return businessType;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public int getSiteId() {
|
||||
return siteId;
|
||||
}
|
||||
|
||||
public int getSeq() {
|
||||
return seq;
|
||||
}
|
||||
|
||||
public int getDrivingStatus() {
|
||||
return drivingStatus;
|
||||
}
|
||||
|
||||
public double getLon() {
|
||||
return lon;
|
||||
}
|
||||
|
||||
public double getLat() {
|
||||
return lat;
|
||||
}
|
||||
|
||||
public void setIfStop(int ifStop) {
|
||||
this.ifStop = ifStop;
|
||||
}
|
||||
|
||||
public int getIfStop() {
|
||||
return ifStop;
|
||||
}
|
||||
|
||||
public void setLeaving(boolean leaving) {
|
||||
this.leaving = leaving;
|
||||
}
|
||||
|
||||
public boolean isLeaving() {
|
||||
return leaving;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BusStationBean{" +
|
||||
"name='" + name + '\'' +
|
||||
", description='" + description + '\'' +
|
||||
", cityCode='" + cityCode + '\'' +
|
||||
", lon=" + lon +
|
||||
", lat=" + lat +
|
||||
", businessType=" + businessType +
|
||||
", status=" + status +
|
||||
", siteId=" + siteId +
|
||||
", seq=" + seq +
|
||||
", drivingStatus=" + drivingStatus +
|
||||
", ifStop=" + ifStop +
|
||||
", leaving=" + leaving +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.mogo.och.sweepers.bean;
|
||||
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
|
||||
import com.mogo.commons.network.Utils;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2021/3/22
|
||||
*
|
||||
* 小巴车运营状态请求参数
|
||||
*/
|
||||
public class SweepersUpdateSiteStatusRequest {
|
||||
|
||||
public String sn;
|
||||
public int seq;//站点序号
|
||||
public int siteId;//站点id
|
||||
public double lon;
|
||||
public double lat;
|
||||
|
||||
public SweepersUpdateSiteStatusRequest(int seq, int siteId, double lon, double lat) {
|
||||
this.sn = MoGoAiCloudClientConfig.getInstance().getSn();
|
||||
this.seq = seq;
|
||||
this.siteId = siteId;
|
||||
this.lon = lon;
|
||||
this.lat = lat;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.mogo.och.sweepers.callback;
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2021/10/22
|
||||
*/
|
||||
public interface ICarOperationStatusCallback {
|
||||
void changeOperationStatus(boolean changeStatus);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.mogo.och.sweepers.callback;
|
||||
|
||||
import com.mogo.och.sweepers.bean.SweepersStationBean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2021/10/22
|
||||
*/
|
||||
public interface IRefreshSweepersStationsCallback {
|
||||
void refreshBusStations(String lineName, List<SweepersStationBean> stationList, int currentStation, int nextStation, boolean isArrived);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.mogo.och.sweepers.callback;
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2021/10/22
|
||||
*/
|
||||
public interface ISlidePannelHideCallback {
|
||||
void hideSlidePanel();
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.mogo.och.sweepers.callback;
|
||||
|
||||
import android.location.Location;
|
||||
|
||||
/**
|
||||
* Created on 2021/9/10
|
||||
*
|
||||
* Model->Presenter回调:状态控制器监听(accOn、adas ui show、voice ui show、push ui show、v2x ui show等等)
|
||||
*/
|
||||
public interface ISweepersControllerStatusCallback {
|
||||
// 是否vr map模式
|
||||
void onVRModeChanged(boolean isVRMode);
|
||||
// 自车定位
|
||||
void onCarLocationChanged(Location location);
|
||||
//开始开启自动驾驶
|
||||
void startOpenAutopilot();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.mogo.och.sweepers.callback;
|
||||
|
||||
import com.mogo.och.sweepers.bean.SweepersQueryLinesResponse;
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2022/2/9
|
||||
*/
|
||||
public interface ISweepersLinesCallback {
|
||||
void onBusLinesChange(SweepersQueryLinesResponse lines);
|
||||
void onChangeLineIdSuccess();
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.mogo.och.sweepers.constant
|
||||
|
||||
import com.mogo.commons.debug.DebugConfig
|
||||
|
||||
/**
|
||||
* Created on 2021/12/6
|
||||
*/
|
||||
class SweepersConst {
|
||||
companion object {
|
||||
|
||||
private const val BASE_URL_OCH_DEV = "http://tech-dev.zhidaohulian.com"
|
||||
private const val BASE_URL_OCH_QA = "https://tech-qa.zhidaohulian.com"
|
||||
private const val BASE_URL_OCH_RELEASE = "https://tech.zhidaohulian.com"
|
||||
|
||||
@JvmStatic
|
||||
fun getBaseUrl(): String {
|
||||
return when (DebugConfig.getNetMode()) {
|
||||
DebugConfig.NET_MODE_DEV, DebugConfig.NET_MODE_DEMO -> BASE_URL_OCH_DEV
|
||||
DebugConfig.NET_MODE_QA -> BASE_URL_OCH_QA
|
||||
DebugConfig.NET_MODE_RELEASE -> BASE_URL_OCH_RELEASE
|
||||
else -> BASE_URL_OCH_RELEASE
|
||||
}
|
||||
}
|
||||
|
||||
// OCH arouter 路由path
|
||||
const val PATH = "/och/api"
|
||||
|
||||
// 测试用的广播
|
||||
const val BROADCAST_TEST_SWEEPERS_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 SWEEPERS_START_MAP_MAKER = "sweepers_start_map_maker";
|
||||
//终点UUID
|
||||
const val SWEEPERS_END_MAP_MAKER = "sweepers_end_map_maker";
|
||||
|
||||
// 埋点key:接管后点击'自动驾驶'按钮启动
|
||||
const val EVENT_KEY_RESTART_AUTOPILOT = "event_key_och_sweepers_restart_autopilot"
|
||||
// 埋点key:开始服务开启自动驾驶(成功/失败)
|
||||
const val EVENT_KEY_START_SERVICE = "event_key_och_sweepers_start_service"
|
||||
const val EVENT_PARAM_SN = "sn"
|
||||
const val EVENT_PARAM_TIME = "time"
|
||||
const val EVENT_PARAM_START_NAME = "start_name"
|
||||
const val EVENT_PARAM_END_NAME = "end_name"
|
||||
const val EVENT_PARAM_LINE_ID = "line_id"
|
||||
const val EVENT_PARAM_START_RESULT = "start_autopilot" // true/false
|
||||
const val EVENT_PARAM_PLATE_NUM = "plate_number" // 车牌号
|
||||
const val EVENT_PARAM_ENV_ONLINE = "env_online" // 是否线上环境:true/false
|
||||
|
||||
/**
|
||||
* 订单起终点Marker类型
|
||||
*/
|
||||
const val TYPE_MARKER_SWEEPERS_ORDER = "TYPE_MARKER_SWEEPERS_ORDER"
|
||||
|
||||
const val TIMER_START_AUTOPILOT_INTERVAL = 20 * 1000L
|
||||
|
||||
//围栏到站 暂定10米
|
||||
const val ARRIVE_AT_END_STATION_DISTANCE = 10
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,565 @@
|
||||
package com.mogo.och.sweepers.fragment;
|
||||
|
||||
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS;
|
||||
import static com.mogo.och.sweepers.constant.SweepersConst.TIMER_START_AUTOPILOT_INTERVAL;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Intent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.constraintlayout.widget.Group;
|
||||
|
||||
import com.mogo.commons.AbsMogoApplication;
|
||||
import com.mogo.commons.debug.DebugConfig;
|
||||
import com.mogo.commons.mvp.IView;
|
||||
import com.mogo.commons.mvp.MvpFragment;
|
||||
import com.mogo.commons.mvp.Presenter;
|
||||
import com.mogo.eagle.core.data.config.HmiBuildConfig;
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotRecordListener;
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener;
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager;
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotRecordListenerManager;
|
||||
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager;
|
||||
import com.mogo.eagle.core.function.call.hmi.CallerHmiManager;
|
||||
import com.mogo.eagle.core.function.hmi.ui.widget.TrafficDataView;
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
|
||||
import com.mogo.eagle.core.utilcode.util.ToastUtils;
|
||||
import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
|
||||
import com.mogo.map.MogoMapUIController;
|
||||
import com.mogo.map.MogoMarkerManager;
|
||||
import com.mogo.map.listener.IMogoMapListener;
|
||||
import com.mogo.map.uicontroller.VisualAngleMode;
|
||||
import com.mogo.module.common.MogoApisHandler;
|
||||
import com.mogo.module.common.constants.DataTypes;
|
||||
import com.mogo.module.common.view.OnPreventFastClickListener;
|
||||
import com.mogo.och.sweepers.R;
|
||||
import com.mogo.och.sweepers.bean.SweepersRoutesResult;
|
||||
import com.mogo.och.sweepers.constant.SweepersConst;
|
||||
import com.mogo.och.sweepers.model.SweepersOrderModel;
|
||||
import com.mogo.och.sweepers.util.BDRouteDataTestUtils;
|
||||
import com.mogo.och.sweepers.view.SlidePanelView;
|
||||
|
||||
import mogo.telematics.pad.MessagePad;
|
||||
import record_cache.RecordPanelOuterClass;
|
||||
|
||||
/**
|
||||
* 网约车基础Fragment,主要负责布局通用界面,处理站点面板和通话面板互斥情况
|
||||
* <p>
|
||||
* 部分业务放在了此处处理
|
||||
*
|
||||
* @author tongchenfei
|
||||
*/
|
||||
public abstract class BaseSweepersTabFragment<V extends IView, P extends Presenter<V>> extends MvpFragment<V, P> implements IMogoMapListener, IMoGoAutopilotRecordListener {
|
||||
|
||||
private static final String TAG = "BaseOchFragment";
|
||||
|
||||
protected SlidePanelView slidePanelView;
|
||||
private RelativeLayout ctvAutopilotStatus;
|
||||
private ImageView ctvAutopilotStatusIv;
|
||||
private TextView ctvAutopilotStatusTv;
|
||||
protected TextView tvOperationStatus;
|
||||
protected RelativeLayout mSettingBtn;
|
||||
protected RelativeLayout mBadcaseBtn;
|
||||
protected RelativeLayout mAICollectBtn;
|
||||
public boolean isOperationStatus;//false-收车,true-出车
|
||||
private FrameLayout flStationPanelContainer;
|
||||
private Group groupTestPanel;
|
||||
private FrameLayout flSpeed;
|
||||
// private BusArcView mouduleArc;
|
||||
private TrafficDataView mTrafficDataView;
|
||||
private ImageView mUpgradeTipIv;
|
||||
// private BusTrafficLightView mTrafficLightView;
|
||||
|
||||
public static final String TYPE_ENTRANCE = "entrance";
|
||||
|
||||
//远景和中景的切换
|
||||
private ImageView mSwitchMapModeImage;
|
||||
private LinearLayout mSwitchMapModeLayout;
|
||||
|
||||
private ObjectAnimator autopilotLoadingAnimator;
|
||||
|
||||
public boolean isAnimateRunning = false;
|
||||
|
||||
/**
|
||||
* 滑动按钮触发的事件
|
||||
*/
|
||||
private final SlidePanelView.OnSlidePanelMoveToEndListener onSlideToEndListener = () -> {
|
||||
// 此处做一个代理,处理一下共有情况
|
||||
if (getSlidePanelOnEndListener() != null) {
|
||||
getSlidePanelOnEndListener().moveToEnd();
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.sweepers_base_fragment;
|
||||
}
|
||||
|
||||
private View panelView;
|
||||
|
||||
@Override
|
||||
protected void initViews() {
|
||||
groupTestPanel = findViewById(R.id.groupTestPanel);
|
||||
slidePanelView = findViewById(R.id.module_mogo_och_slide_panel);
|
||||
ctvAutopilotStatus = findViewById(R.id.module_mogo_och_autopilot_status);
|
||||
ctvAutopilotStatusIv = findViewById(R.id.sweepers_autopilot_btn_iv);
|
||||
ctvAutopilotStatusTv = findViewById(R.id.sweepers_autopolot_btn_tv);
|
||||
flStationPanelContainer = findViewById(R.id.module_mogo_och_station_panel_container);
|
||||
|
||||
// mTrafficLightView = findViewById(R.id.bus_traffic_light_view);
|
||||
// CallerHmiManager.INSTANCE.setProxyTrafficLightView(mTrafficLightView);
|
||||
|
||||
tvOperationStatus = findViewById(R.id.module_mogo_och_operation_status);
|
||||
|
||||
flSpeed = (FrameLayout) findViewById(R.id.fl_speed);
|
||||
mTrafficDataView = (TrafficDataView) findViewById(R.id.sweepers_arc);
|
||||
|
||||
panelView = LayoutInflater.from(getContext()).inflate(getStationPanelViewId(), flStationPanelContainer);
|
||||
slidePanelView.setOnSlidePanelMoveToEndListener(onSlideToEndListener);
|
||||
|
||||
mSwitchMapModeLayout = findViewById(R.id.sweepers_switch_model_layout);
|
||||
mSwitchMapModeImage = findViewById(R.id.sweepers_switch_model_icon);
|
||||
updateSwitchMapIcon();
|
||||
|
||||
mSwitchMapModeLayout.setOnClickListener(new OnPreventFastClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClickImpl(View v) {
|
||||
//切换地图的远近视图
|
||||
if (MogoMapUIController.getInstance().getCurrentMapVisualAngle().isLongSight()) {
|
||||
MogoMarkerManager.getInstance(AbsMogoApplication.getApp()).visibleAllMarkers();
|
||||
MogoMapUIController.getInstance().changeMapVisualAngle(VisualAngleMode.MODE_MEDIUM_SIGHT, null);
|
||||
mSwitchMapModeImage.setImageResource(R.drawable.sweepers_switch_map_medium);
|
||||
} else if (MogoMapUIController.getInstance().getCurrentMapVisualAngle().isMediumSight()) {
|
||||
MogoMarkerManager.getInstance(AbsMogoApplication.getApp())
|
||||
.inVisibleWithoutMarkers(DataTypes.TYPE_MARKER_ADAS, SweepersConst.TYPE_MARKER_SWEEPERS_ORDER);
|
||||
MogoMapUIController.getInstance().changeMapVisualAngle(VisualAngleMode.MODE_LONG_SIGHT, null);
|
||||
mSwitchMapModeImage.setImageResource(R.drawable.sweepers_switch_map_long);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (DebugConfig.isDebug()) {
|
||||
mTrafficDataView.setLongClickable(true);
|
||||
mTrafficDataView.setOnLongClickListener(v -> {
|
||||
CallerLogger.INSTANCE.d(M_BUS + TAG, "长按显示状态工具栏");
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("oper", 52);
|
||||
MogoApisHandler.getInstance().getApis().getIntentManagerApi().invoke("com.mogo.mock", intent);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
initListener();
|
||||
ctvAutopilotStatus.setOnClickListener(new OnPreventFastClickListener(){
|
||||
|
||||
@Override
|
||||
public void onClickImpl(View v) {
|
||||
if (CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE){
|
||||
restartAutopilot();
|
||||
}else {
|
||||
ToastUtils.showShort(getResources().getString(R.string.sweepers_auto_disable_tip));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
setAutopilotBtnStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState());
|
||||
// 模拟 不可自动驾驶,目前场景是刚开机,adas还未和工控机连接
|
||||
findViewById(R.id.btnAutopilotDisable).setOnClickListener(view ->
|
||||
debugAutoPilotStatus(IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE)
|
||||
);
|
||||
|
||||
// 模拟 可自动驾驶,工控机连接正常,且处于人工干预状态
|
||||
findViewById(R.id.btnAutopilotEnable).setOnClickListener(view ->
|
||||
debugAutoPilotStatus(IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE)
|
||||
);
|
||||
|
||||
// 模拟 自动驾驶能力,自动驾驶中,可能是停车,可能是行进,但是是机器在处理车的前进后退,不是人
|
||||
findViewById(R.id.btnAutopilotRunning).setOnClickListener(view ->
|
||||
debugAutoPilotStatus(IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING)
|
||||
);
|
||||
|
||||
// 模拟 自动驾驶网约车回调数据
|
||||
findViewById(R.id.btnAutopilotArrive).setOnClickListener(view ->
|
||||
debugArrivedStation()
|
||||
);
|
||||
|
||||
findViewById(R.id.btnAutopilotRoute).setOnClickListener(view -> debugArrivedRoute());
|
||||
|
||||
tvOperationStatus.setOnClickListener(view -> {
|
||||
onChangeOperationStatus();
|
||||
});
|
||||
|
||||
mSettingBtn = findViewById(R.id.module_mogo_och_setting_layout);
|
||||
mSettingBtn.setOnClickListener(v -> {
|
||||
// TODO: 2021/12/9
|
||||
CallerHmiManager.INSTANCE.showToolsView();
|
||||
});
|
||||
|
||||
// mBadcaseBtn的visible显示逻辑在showBadcaseEntrance内处理
|
||||
mBadcaseBtn = findViewById(R.id.module_mogo_och_badcase_rl);
|
||||
// CallerHmiManager.INSTANCE.registerBadCaseCallback(
|
||||
// () -> { // onShow()
|
||||
// return mBadcaseBtn; },
|
||||
// () -> { // onHide()
|
||||
// return null; });
|
||||
|
||||
if (mBadcaseBtn != null) {
|
||||
CallerDevaToolsManager.INSTANCE.initBadCase(mBadcaseBtn);
|
||||
if (!HmiBuildConfig.isShowBadCaseView) {
|
||||
CallerAutopilotRecordListenerManager.INSTANCE.addListener(TAG, this);
|
||||
}
|
||||
}
|
||||
|
||||
mAICollectBtn = findViewById(R.id.module_mogo_och_ai_collet_rl);
|
||||
if (mAICollectBtn != null){
|
||||
CallerDevaToolsManager.INSTANCE.initAiCollect(mAICollectBtn);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSwitchMapIcon(){
|
||||
if (MogoMapUIController.getInstance().getCurrentMapVisualAngle().isLongSight()) {
|
||||
mSwitchMapModeImage.setImageResource(R.drawable.sweepers_switch_map_long);
|
||||
} else if (MogoMapUIController.getInstance().getCurrentMapVisualAngle().isMediumSight()) {
|
||||
mSwitchMapModeImage.setImageResource(R.drawable.sweepers_switch_map_medium);
|
||||
} else {
|
||||
mSwitchMapModeImage.setImageResource(R.drawable.sweepers_switch_map_medium);
|
||||
}
|
||||
}
|
||||
|
||||
private void debugArrivedRoute() {
|
||||
BDRouteDataTestUtils.converToRouteData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
if (!HmiBuildConfig.isShowBadCaseView) {
|
||||
CallerAutopilotRecordListenerManager.INSTANCE.removeListener(TAG);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onAutopilotRecordResult(@Nullable RecordPanelOuterClass.RecordPanel recordPanel) {
|
||||
// if (!HmiBuildConfig.isShowBadCaseView && recordPanel != null && recordPanel.getType() == 1 && recordPanel.getStat() == 100) {
|
||||
// CallerDevaToolsManager.INSTANCE.onReceiveBadCaseRecord(recordPanel);
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAutopilotRecordConfig(@NonNull MessagePad.RecordDataConfig config) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 测试到站
|
||||
*/
|
||||
protected abstract void debugArrivedStation();
|
||||
|
||||
private void initListener() {
|
||||
MogoApisHandler.getInstance().getApis().getRegisterCenterApi().registerMogoMapListener(TYPE_ENTRANCE, this);
|
||||
}
|
||||
|
||||
protected void onChangeOperationStatus() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 展示滑动按钮
|
||||
*
|
||||
* @param text 指定的文字
|
||||
*/
|
||||
public void showSlidePanle(String text) {
|
||||
if (isOperationStatus) {
|
||||
getActivity().runOnUiThread(() -> {
|
||||
slidePanelView.setText(text);
|
||||
slidePanelView.setVisibility(View.VISIBLE);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏滑动按钮
|
||||
*/
|
||||
public void hideSlidePanel() {
|
||||
getActivity().runOnUiThread(() -> {
|
||||
slidePanelView.setVisibility(View.GONE);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 改变自动驾驶状态
|
||||
*
|
||||
* @param autopilotStatus 0:不可用 1:可用状态 2:自动驾驶中
|
||||
*/
|
||||
public void onAutopilotStatusChanged(int autopilotStatus) {
|
||||
getActivity().runOnUiThread(() -> {
|
||||
changeAutopilotBtnView(autopilotStatus, isAnimateRunning);
|
||||
});
|
||||
}
|
||||
|
||||
public void setAutopilotBtnStatus(int autopilotStatus) {
|
||||
if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE
|
||||
== autopilotStatus) {//0不可用
|
||||
ctvAutopilotStatusTv.setTextColor(getResources().getColor(R.color.sweepers_autopilot_text_color_disable));
|
||||
ctvAutopilotStatusTv.setText(getResources().getString(R.string.sweepers_loading_autopilot_runnig_tv));
|
||||
ctvAutopilotStatusIv.setImageResource(R.drawable.sweepers_disable_autopilot_icon);
|
||||
ctvAutopilotStatus.setSelected(false);
|
||||
ctvAutopilotStatus.setFocusableInTouchMode(true);
|
||||
|
||||
} else {
|
||||
ctvAutopilotStatusTv.setTextColor(getResources().getColor(R.color.sweepers_autopilot_text_color_normal));
|
||||
ctvAutopilotStatusTv.setText(getResources().getString(R.string.sweepers_loading_autopilot_runnig_tv));
|
||||
ctvAutopilotStatusIv.setImageResource(R.drawable.sweepers_ic_autopilot);
|
||||
ctvAutopilotStatus.setFocusableInTouchMode(true);
|
||||
if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE == autopilotStatus) {//1可用
|
||||
ctvAutopilotStatus.setSelected(false);
|
||||
}else if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING == autopilotStatus){
|
||||
ctvAutopilotStatus.setSelected(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateAutopilotStatus(int autopilotStatus){
|
||||
if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING
|
||||
== autopilotStatus) {//2 running
|
||||
ctvAutopilotStatusIv.setImageResource(R.drawable.sweepers_right_autopilot_icon);
|
||||
ctvAutopilotStatusTv.setTextColor(getResources().getColor(R.color.sweepers_autopilot_text_color_normal));
|
||||
ctvAutopilotStatusTv.setText(getResources().getString(R.string.sweepers_loading_autopilot_success_tv));
|
||||
ctvAutopilotStatus.setSelected(false);
|
||||
ctvAutopilotStatus.setFocusableInTouchMode(false);
|
||||
}else {
|
||||
ctvAutopilotStatusIv.setImageResource(R.drawable.sweepers_wrong_autopilot_icon);
|
||||
ctvAutopilotStatusTv.setTextColor(getResources().getColor(R.color.sweepers_autopilot_text_color_normal));
|
||||
ctvAutopilotStatusTv.setText(getResources().getString(R.string.sweepers_loading_autopilot_failure_tv));
|
||||
ctvAutopilotStatus.setFocusableInTouchMode(false);
|
||||
ctvAutopilotStatus.setSelected(false);
|
||||
}
|
||||
UiThreadHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setAutopilotBtnStatus(autopilotStatus);
|
||||
}
|
||||
},1000);
|
||||
}
|
||||
|
||||
private void changeAutopilotBtnView(int autopilotStatus, boolean isAnimateRunning) {
|
||||
CallerLogger.INSTANCE.d(M_BUS + TAG, "onStateChangeChangeAutopilotBtnView: "
|
||||
+ autopilotStatus + "isAnimateRunning = " + isAnimateRunning);
|
||||
if (isAnimateRunning && IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING
|
||||
!= autopilotStatus) {
|
||||
// 主动开启自动驾驶中,不为2(为0、1)则继续loading
|
||||
return;
|
||||
}
|
||||
if (isAnimateRunning){
|
||||
stopAutopilotAnimation();
|
||||
updateAutopilotStatus(autopilotStatus);
|
||||
}else {
|
||||
setAutopilotBtnStatus(autopilotStatus);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏【自动驾驶】按钮
|
||||
*/
|
||||
public void hideAutopilotBiz() {
|
||||
getActivity().runOnUiThread(() -> {
|
||||
// ctvAutopilotStatus.setVisibility(View.GONE);
|
||||
// slidePanelView.setVisibility(View.GONE);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 展示【自动驾驶】按钮
|
||||
*/
|
||||
public void showAutopilotBiz() {
|
||||
getActivity().runOnUiThread(() -> {
|
||||
ctvAutopilotStatus.setVisibility(View.VISIBLE);
|
||||
});
|
||||
}
|
||||
|
||||
public void hidPanel() {
|
||||
getActivity().runOnUiThread(() -> {
|
||||
flStationPanelContainer.setVisibility(View.GONE);
|
||||
});
|
||||
}
|
||||
|
||||
public void showPanel() {
|
||||
getActivity().runOnUiThread(() -> {
|
||||
flStationPanelContainer.setVisibility(View.VISIBLE);
|
||||
});
|
||||
}
|
||||
|
||||
public View getPanelView() {
|
||||
return panelView;
|
||||
}
|
||||
|
||||
public SlidePanelView.OnSlidePanelMoveToEndListener getSlidePanelOnEndListener() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取站点面板view,在{@link #initViews()}时候添加到container中
|
||||
*
|
||||
* @return 站点面板view
|
||||
*/
|
||||
public abstract int getStationPanelViewId();
|
||||
|
||||
/**
|
||||
* 重新开启自动驾驶
|
||||
*/
|
||||
public abstract void restartAutopilot();
|
||||
|
||||
/**
|
||||
* 模拟自动驾驶返回状态
|
||||
*
|
||||
* @param status
|
||||
*/
|
||||
public abstract void debugAutoPilotStatus(int status);
|
||||
|
||||
/**
|
||||
* 开启自动驾驶中间动画
|
||||
*/
|
||||
public void startAutopilotAnimation() {
|
||||
isAnimateRunning = true;
|
||||
ctvAutopilotStatusTv.setText(getResources().getString(R.string.sweepers_loading_autopilot_tv));
|
||||
ctvAutopilotStatusTv.setTextColor(getResources().getColor(R.color.sweepers_autopilot_text_color_normal));
|
||||
ctvAutopilotStatus.setSelected(false);
|
||||
ctvAutopilotStatus.setFocusableInTouchMode(true);
|
||||
ctvAutopilotStatusIv.setImageResource(R.drawable.sweepers_loading_autopilot_icon);
|
||||
if (autopilotLoadingAnimator == null) {
|
||||
autopilotLoadingAnimator = ObjectAnimator.ofFloat(ctvAutopilotStatusIv, "rotation", 0f, 360f);
|
||||
autopilotLoadingAnimator.setInterpolator(new LinearInterpolator());
|
||||
autopilotLoadingAnimator.setRepeatCount(-1);//无限循环
|
||||
autopilotLoadingAnimator.setDuration(1000);//设置持续时间
|
||||
}
|
||||
autopilotLoadingAnimator.start();//动画开始
|
||||
|
||||
startingAutoApilotCountDown();
|
||||
|
||||
}
|
||||
|
||||
private void startingAutoApilotCountDown(){
|
||||
//10s 若自动驾驶没有开启,则结束动画
|
||||
UiThreadHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() { //未启动成功做处理
|
||||
if (isAnimateRunning){// 只判断动画是否在进行,根据自动驾驶当前状态去设置自动驾驶状态
|
||||
stopAutopilotAnimation();
|
||||
updateAutopilotStatus(CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState());
|
||||
}
|
||||
}
|
||||
},TIMER_START_AUTOPILOT_INTERVAL);
|
||||
|
||||
}
|
||||
/**
|
||||
* 停止自动驾驶中间动画
|
||||
*/
|
||||
protected void stopAutopilotAnimation() {
|
||||
if (autopilotLoadingAnimator != null) {
|
||||
autopilotLoadingAnimator.end();
|
||||
ctvAutopilotStatusIv.clearAnimation();
|
||||
autopilotLoadingAnimator = null;
|
||||
isAnimateRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 迈速表实时更新
|
||||
*
|
||||
* @param newSpeed
|
||||
*/
|
||||
public void updateSpeedView(float newSpeed) {
|
||||
int speed = (int) (Math.abs(newSpeed) * 3.6F); // 倒车时工控机反馈定位信息中speed为负值
|
||||
if (mTrafficDataView != null){
|
||||
mTrafficDataView.updateSpeedWithValue(speed);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
MogoApisHandler.getInstance().getApis().getRegisterCenterApi().unregisterMogoMapListener(TYPE_ENTRANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMapVisualAngleChanged(VisualAngleMode visualAngleMode) {
|
||||
if (visualAngleMode.isMediumSight()) {
|
||||
mSwitchMapModeLayout.setVisibility(View.VISIBLE);
|
||||
} else if (visualAngleMode.isLongSight()) {
|
||||
mSwitchMapModeLayout.setVisibility(View.VISIBLE);
|
||||
} else if (visualAngleMode.isCloseSight()) {
|
||||
mSwitchMapModeLayout.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* bus调试面板打开关闭
|
||||
*/
|
||||
public void debugTestBar() {
|
||||
if (groupTestPanel.getVisibility() == View.VISIBLE) {
|
||||
groupTestPanel.setVisibility(View.GONE);
|
||||
} else {
|
||||
groupTestPanel.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bus调试信息:线路、轨迹等信息
|
||||
*
|
||||
* START
|
||||
*/
|
||||
private View busTestBar;
|
||||
private TextView lineIdTV;
|
||||
private TextView trajMd5TV;
|
||||
private TextView stopMd5TV;
|
||||
private TextView trajMd5DPQPTV;
|
||||
private TextView stopMd5DPQPTV;
|
||||
|
||||
public void showHideTestBar() {
|
||||
if (busTestBar == null) {
|
||||
busTestBar = findViewById(R.id.module_mogo_och_sweepers_test_bar);
|
||||
lineIdTV = findViewById(R.id.sweepers_test_bar_current_line_id);
|
||||
trajMd5TV = findViewById(R.id.sweepers_test_bar_current_traj_md5);
|
||||
stopMd5TV = findViewById(R.id.sweepers_test_bar_current_stop_md5);
|
||||
trajMd5DPQPTV = findViewById(R.id.sweepers_test_bar_current_traj_md5_dpqp);
|
||||
stopMd5DPQPTV = findViewById(R.id.sweepers_test_bar_current_stop_md5_dpqp);
|
||||
}
|
||||
|
||||
if (busTestBar.getVisibility() == View.VISIBLE) {
|
||||
busTestBar.setVisibility(View.GONE);
|
||||
} else {
|
||||
SweepersRoutesResult routesResult = SweepersOrderModel.getInstance().getBusRoutesResult();
|
||||
lineIdTV.setText("lineId:" + (routesResult == null ? "" : String.valueOf(routesResult.getLineId())));
|
||||
trajMd5TV.setText("TMd5:" + (routesResult == null ? "" : routesResult.csvFileMd5));
|
||||
stopMd5TV.setText("SMd5:" + (routesResult == null ? "" : routesResult.txtFileMd5));
|
||||
trajMd5DPQPTV.setText("TMd5DPQP:" + (routesResult == null ? "" : routesResult.csvFileMd5DPQP));
|
||||
stopMd5DPQPTV.setText("SMd5DPQP:" + (routesResult == null ? "" : routesResult.txtFileMd5DPQP));
|
||||
busTestBar.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateSweepersTestBarInfo() {
|
||||
if (busTestBar != null && busTestBar.getVisibility() == View.VISIBLE) {
|
||||
SweepersRoutesResult routesResult = SweepersOrderModel.getInstance().getBusRoutesResult();
|
||||
lineIdTV.setText("lineId:" + (routesResult == null ? "" : String.valueOf(routesResult.getLineId())));
|
||||
trajMd5TV.setText("TMd5:" + (routesResult == null ? "" : routesResult.csvFileMd5));
|
||||
stopMd5TV.setText("SMd5:" + (routesResult == null ? "" : routesResult.txtFileMd5));
|
||||
trajMd5DPQPTV.setText("TMd5DPQP:" + (routesResult == null ? "" : routesResult.csvFileMd5DPQP));
|
||||
stopMd5DPQPTV.setText("SMd5DPQP:" + (routesResult == null ? "" : routesResult.txtFileMd5DPQP));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* END
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,401 @@
|
||||
package com.mogo.och.sweepers.fragment;
|
||||
|
||||
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.mogo.commons.AbsMogoApplication;
|
||||
import com.mogo.commons.debug.DebugConfig;
|
||||
import com.mogo.commons.voice.AIAssist;
|
||||
import com.mogo.eagle.core.data.map.CenterLine;
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener;
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager;
|
||||
import com.mogo.eagle.core.function.call.map.CallerHDMapManager;
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
|
||||
import com.mogo.eagle.core.utilcode.util.ToastUtils;
|
||||
import com.mogo.map.MogoMarkerManager;
|
||||
import com.mogo.map.marker.IMogoMarker;
|
||||
import com.mogo.map.marker.MogoMarkerOptions;
|
||||
import com.mogo.och.sweepers.R;
|
||||
import com.mogo.och.sweepers.bean.SweepersStationBean;
|
||||
import com.mogo.och.sweepers.constant.SweepersConst;
|
||||
import com.mogo.och.sweepers.presenter.SweepersPresenter;
|
||||
import com.mogo.och.sweepers.ui.SweepersSwitchLineActivity;
|
||||
import com.mogo.och.sweepers.view.SlidePanelView;
|
||||
import com.mogo.och.common.module.utils.OCHThreadPoolManager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* 网约车小巴界面
|
||||
*
|
||||
* @author tongchenfei
|
||||
*/
|
||||
public class SweepersFragment extends BaseSweepersTabFragment<SweepersFragment, SweepersPresenter>
|
||||
implements SlidePanelView.OnSlidePanelMoveToEndListener, View.OnClickListener {
|
||||
private static final String TAG = "SweepersFragment";
|
||||
|
||||
private TextView mCurrentStationName;
|
||||
private TextView mNextStationName;
|
||||
private TextView mCurrentTag;
|
||||
private TextView mNextTag;
|
||||
private TextView mSwitchLine; //切换路线
|
||||
private TextView mLineName;
|
||||
private int mCurrentStation = 0;
|
||||
|
||||
private View mSweepers;
|
||||
|
||||
private SweepersStationBean startStation = null;
|
||||
private SweepersStationBean endStation = null;
|
||||
|
||||
@Override
|
||||
public String getTagName() {
|
||||
return "SweepersFragment";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initViews() {
|
||||
super.initViews();
|
||||
mSweepers = findViewById(R.id.module_och_sweepers_tag);
|
||||
mCurrentStationName = findViewById(R.id.module_och_sweepers_current_station);
|
||||
mCurrentTag = findViewById(R.id.module_och_sweepers_current_station_anchor);
|
||||
mNextStationName = findViewById(R.id.module_och_sweepers_order_end_station);
|
||||
mNextTag = findViewById(R.id.module_och_sweepers_next_station_anchor);
|
||||
mSwitchLine = findViewById(R.id.switch_line_btn);
|
||||
mLineName = findViewById(R.id.module_och_sweepers_line_name);
|
||||
|
||||
if (DebugConfig.isDebug()) {
|
||||
mSweepers.setOnClickListener(view -> {
|
||||
ToastUtils.showShort("重置了车站状态");
|
||||
mPresenter.querySweepersRoutes();
|
||||
});
|
||||
|
||||
//debug下调用测试面板
|
||||
mCurrentStationName.setOnLongClickListener(v -> {
|
||||
debugTestBar();
|
||||
showHideTestBar();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
CallerLogger.INSTANCE.d(M_BUS + TAG, "initView: " + CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState());
|
||||
// 初始化的时候设置 UI 按钮状态
|
||||
switch (CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()) {
|
||||
case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE:
|
||||
hideAutopilotBiz();
|
||||
break;
|
||||
case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE:
|
||||
showAutopilotBiz();
|
||||
onAutopilotStatusChanged(IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE);
|
||||
break;
|
||||
case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING:
|
||||
showAutopilotBiz();
|
||||
onAutopilotStatusChanged(IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mSwitchLine.setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void debugArrivedStation() {
|
||||
mPresenter.onAutopilotArriveAtStation(null);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected SweepersPresenter createPresenter() {
|
||||
return new SweepersPresenter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据站点列表信息刷新车站面板,滑块面板
|
||||
*
|
||||
* @param stationList 车站列表信息
|
||||
* @param currentStation 当前站点
|
||||
* @param nextStation 下个站点
|
||||
* @param isArrived 是否都站
|
||||
*/
|
||||
public void refreshSweepersStations(String lineName, List<SweepersStationBean> stationList
|
||||
, int currentStation, int nextStation, boolean isArrived) {
|
||||
mCurrentStation = currentStation;
|
||||
if (getActivity() == null) {
|
||||
return;
|
||||
}
|
||||
getActivity().runOnUiThread(() -> {
|
||||
if (stationList == null) {
|
||||
// 获取小巴数据失败
|
||||
return;
|
||||
}
|
||||
|
||||
// 渲染小巴路线数据
|
||||
renderCurrentStationStatus(lineName,stationList, currentStation, nextStation, isArrived);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新刷新站点信息 isArrived 是否到站
|
||||
*/
|
||||
private void renderCurrentStationStatus(String lineName, List<SweepersStationBean> stationList, int currentStation
|
||||
, int nextStation, boolean isArrived) {
|
||||
CallerLogger.INSTANCE.d(M_BUS + "MapMaker ", "currentStation=" + currentStation + ",nextStation=" + nextStation + "isArrived=" + isArrived);
|
||||
String currentStationName = null;
|
||||
String nextStationName = null;
|
||||
|
||||
boolean isArriveEndStation = false;
|
||||
boolean isArriveAtStation = false;
|
||||
boolean isArriveAtStartStation = false;
|
||||
|
||||
mLineName.setText(lineName);
|
||||
|
||||
// 获取当前站点的名称
|
||||
currentStationName = stationList.get(currentStation).getName();
|
||||
|
||||
startStation = stationList.get(0);
|
||||
endStation = stationList.get(stationList.size() - 1);
|
||||
|
||||
// 是否到达起点
|
||||
if (currentStation == 0) {
|
||||
isArriveAtStartStation = true;
|
||||
mCurrentTag.setText(getResources().getString(R.string.sweepers_arrive_to_end_start));
|
||||
|
||||
setOrRemoveMapMaker(true, SweepersConst.SWEEPERS_START_MAP_MAKER, startStation.getLat()
|
||||
, startStation.getLon(),R.raw.star_marker);
|
||||
setOrRemoveMapMaker(true, SweepersConst.SWEEPERS_END_MAP_MAKER, endStation.getLat()
|
||||
, endStation.getLon(),R.raw.end_marker);
|
||||
} else if (currentStation > 0 && currentStation < stationList.size() - 1) {// 是否到达站点
|
||||
isArriveAtStation = true;
|
||||
mCurrentTag.setText(getResources().getString(R.string.sweepers_arrive_to_current_tag));
|
||||
mNextTag.setText(getResources().getString(R.string.sweepers_arrive_to_next_tag));
|
||||
|
||||
setOrRemoveMapMaker(false, SweepersConst.SWEEPERS_START_MAP_MAKER, startStation.getLat()
|
||||
, startStation.getLon(),R.raw.star_marker);
|
||||
setOrRemoveMapMaker(true, SweepersConst.SWEEPERS_END_MAP_MAKER, endStation.getLat()
|
||||
, endStation.getLon(),R.raw.end_marker);
|
||||
} else if (currentStation == stationList.size() - 1) {// 是否到达终点
|
||||
isArriveEndStation = true;
|
||||
nextStationName = "--";
|
||||
mNextTag.setText(getResources().getString(R.string.sweepers_arrive_to_end_end));
|
||||
|
||||
setOrRemoveMapMaker(false, SweepersConst.SWEEPERS_START_MAP_MAKER, startStation.getLat()
|
||||
, startStation.getLon(),R.raw.star_marker);
|
||||
|
||||
if (isArrived) {
|
||||
setOrRemoveMapMaker(false, SweepersConst.SWEEPERS_END_MAP_MAKER, endStation.getLat()
|
||||
, endStation.getLon(),R.raw.end_marker);
|
||||
} else {
|
||||
setOrRemoveMapMaker(true, SweepersConst.SWEEPERS_END_MAP_MAKER, endStation.getLat()
|
||||
, endStation.getLon(),R.raw.end_marker);
|
||||
}
|
||||
}
|
||||
|
||||
// 获取下一站点名称
|
||||
if (nextStation > currentStation && nextStation <= stationList.size() - 1) {
|
||||
nextStationName = stationList.get(nextStation).getName();
|
||||
}
|
||||
|
||||
// 是否到达终点
|
||||
if ( nextStation == stationList.size() - 1 || nextStation == -1) {
|
||||
mNextTag.setText(getResources().getString(R.string.sweepers_arrive_to_end_end));
|
||||
}else {
|
||||
mNextTag.setText(getResources().getString(R.string.sweepers_arrive_to_next_tag));
|
||||
}
|
||||
|
||||
if (currentStation == 0 && isArrived){
|
||||
showOrHideSwitchLineBtn(true);
|
||||
}else {
|
||||
showOrHideSwitchLineBtn(false);
|
||||
}
|
||||
|
||||
// 重置滑动按钮文字
|
||||
if (isArriveEndStation) {
|
||||
showSlidePanle("单程结束");
|
||||
} else if (isArriveAtStartStation) {
|
||||
showSlidePanle("滑动出发");
|
||||
} else if (isArriveAtStation) {
|
||||
showSlidePanle("滑动出发");
|
||||
}
|
||||
|
||||
mCurrentStationName.setText(currentStationName);
|
||||
mNextStationName.setText(nextStationName);
|
||||
updateSweepersTestBarInfo();
|
||||
}
|
||||
|
||||
private void showOrHideSwitchLineBtn(boolean isShow) {
|
||||
if (isShow){
|
||||
mSwitchLine.setVisibility(View.VISIBLE);
|
||||
}else {
|
||||
mSwitchLine.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
public void hideOchSweepers() {
|
||||
// tvNotice.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStationPanelViewId() {
|
||||
return R.layout.fragment_och_sweepers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restartAutopilot() {
|
||||
if (!isAnimateRunning) {
|
||||
mPresenter.restartAutopilot();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SlidePanelView.OnSlidePanelMoveToEndListener getSlidePanelOnEndListener() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveToEnd() {
|
||||
// 开启自动驾驶到下一站
|
||||
if (isAnimateRunning){
|
||||
stopAutopilotAnimation();
|
||||
}
|
||||
mPresenter.autoDriveToNextStation(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置自动驾驶可用状态
|
||||
*/
|
||||
public void onAutopilotEnableChange(boolean isEnable) {
|
||||
if (isEnable) {
|
||||
showAutopilotBiz();
|
||||
} else {
|
||||
hideAutopilotBiz();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onChangeOperationStatus() {
|
||||
super.onChangeOperationStatus();
|
||||
mPresenter.onChangeOperationStatus();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改经营状态
|
||||
*
|
||||
* @param launch true-收车,false-出车
|
||||
*/
|
||||
public void changeOperationStatus(boolean launch) {
|
||||
isOperationStatus = launch;
|
||||
if (launch) {
|
||||
// 出车的时候重制站点状态
|
||||
mPresenter.querySweepersRoutes();
|
||||
tvOperationStatus.setText("收车");
|
||||
showPanel();
|
||||
} else {
|
||||
AIAssist.getInstance(getContext()).speakTTSVoice("已收车");
|
||||
tvOperationStatus.setText("出车");
|
||||
hideSlidePanel();
|
||||
hidPanel();
|
||||
|
||||
//移除起点终点
|
||||
if (null != startStation) {
|
||||
setOrRemoveMapMaker(false, SweepersConst.SWEEPERS_START_MAP_MAKER, startStation.getLat()
|
||||
, startStation.getLon(),R.raw.star_marker);
|
||||
}
|
||||
if (null != endStation) {
|
||||
setOrRemoveMapMaker(false, SweepersConst.SWEEPERS_END_MAP_MAKER, endStation.getLat()
|
||||
, endStation.getLon(),R.raw.end_marker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* VR模式切换
|
||||
*
|
||||
* @param isVRMode
|
||||
*/
|
||||
public void onVRModeChanged(boolean isVRMode) {
|
||||
if (mRootView != null) {
|
||||
mRootView.setVisibility(isVRMode ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制地图起点终点
|
||||
*
|
||||
* @param isAdd
|
||||
* @param uuid
|
||||
*/
|
||||
private void setOrRemoveMapMaker(boolean isAdd, String uuid, double lat, double longi,int resourceId) {
|
||||
if (isAdd) {
|
||||
Runnable setMapMarkerRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
CallerLogger.INSTANCE.d(M_BUS + "setMapMaker= "+Thread.currentThread().getName(),
|
||||
uuid + "=latitude=" + lat + ",longitude=" + longi);
|
||||
|
||||
MogoMarkerOptions options = new MogoMarkerOptions()
|
||||
.owner(SweepersConst.TYPE_MARKER_SWEEPERS_ORDER)
|
||||
.anchor(0.5f, 0.5f)
|
||||
.set3DMode(true)
|
||||
.gps(true)
|
||||
.controlAngle(true)
|
||||
.icon3DRes(resourceId)
|
||||
.latitude(lat)
|
||||
.longitude(longi);
|
||||
IMogoMarker marker = MogoMarkerManager.getInstance(AbsMogoApplication.getApp()) .addMarker(uuid, options);
|
||||
CenterLine centerLine = CallerHDMapManager.INSTANCE.getCenterLineInfo(
|
||||
longi,lat,-1);
|
||||
if (null != centerLine){ // 有可能鹰眼map为空没有角度。判空使用后可能造成maker角度跟道路角度不一致
|
||||
marker.setRotateAngle(centerLine.getAngle().floatValue());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
OCHThreadPoolManager.getsInstance().execute(setMapMarkerRunnable);
|
||||
|
||||
}else {
|
||||
Runnable removeMapMarkerRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
CallerLogger.INSTANCE.d(M_BUS + "RemoveMapMaker="+Thread.currentThread().getName(),
|
||||
uuid+"=latitude="+lat+",longitude="+longi);
|
||||
MogoMarkerManager.getInstance(AbsMogoApplication.getApp()).removeMarkers(uuid);
|
||||
}
|
||||
};
|
||||
|
||||
OCHThreadPoolManager.getsInstance().execute(removeMapMarkerRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debugAutoPilotStatus(int status) {
|
||||
mPresenter.debugAutoPilotStatus(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v.getId() == R.id.switch_line_btn) {//切换路线条件: 自动驾驶过程中,点击则toast提示:自动驾驶中,不可切换路线
|
||||
//本次行程未结束,不支持切换路线。点击则toast提示:当前行程未完成,不可切换路线
|
||||
if (CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState()
|
||||
== IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) {
|
||||
ToastUtils.showLong(getResources().getString(R.string.sweepers_switch_line_btn_warning1));
|
||||
return;
|
||||
}
|
||||
if (mCurrentStation > 0) {
|
||||
ToastUtils.showLong(getResources().getString(R.string.sweepers_switch_line_btn_warning2));
|
||||
return;
|
||||
}
|
||||
Intent intent = new Intent(getContext(), SweepersSwitchLineActivity.class);
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.mogo.och.sweepers.model;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.mogo.commons.AbsMogoApplication;
|
||||
import com.mogo.eagle.core.utilcode.util.NetworkUtils;
|
||||
import com.mogo.eagle.core.utilcode.util.ToastUtils;
|
||||
import com.mogo.och.sweepers.bean.SweepersQueryLinesResponse;
|
||||
import com.mogo.och.sweepers.bean.SweepersRoutesResponse;
|
||||
import com.mogo.och.sweepers.callback.ISweepersLinesCallback;
|
||||
import com.mogo.och.sweepers.net.SweepersServiceManager;
|
||||
import com.mogo.och.sweepers.net.ISweepersServiceCallback;
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2022/2/9
|
||||
*/
|
||||
public class SweepersLineModel {
|
||||
private static volatile SweepersLineModel sInstance;
|
||||
private Context mContext;
|
||||
private ISweepersLinesCallback mBusLinesCallback;
|
||||
public static SweepersLineModel getInstance() {
|
||||
if ( sInstance == null ) {
|
||||
synchronized ( SweepersLineModel.class ) {
|
||||
if ( sInstance == null ) {
|
||||
sInstance = new SweepersLineModel();
|
||||
}
|
||||
}
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
private SweepersLineModel() {
|
||||
|
||||
}
|
||||
public void init() {
|
||||
mContext = AbsMogoApplication.getApp();
|
||||
}
|
||||
public void setBusLinesCallback(ISweepersLinesCallback callback){
|
||||
mBusLinesCallback = callback;
|
||||
}
|
||||
public void queryBusLines(){
|
||||
SweepersServiceManager.getInstance().queryBusLines(mContext, new ISweepersServiceCallback<SweepersQueryLinesResponse>() {
|
||||
@Override
|
||||
public void onSuccess(SweepersQueryLinesResponse data) {
|
||||
if (null == data && mBusLinesCallback != null) {
|
||||
mBusLinesCallback.onBusLinesChange(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mBusLinesCallback != null){
|
||||
mBusLinesCallback.onBusLinesChange(data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail(String failMsg) {
|
||||
if (!NetworkUtils.isConnected(mContext)) {
|
||||
ToastUtils.showShort("网络异常,请稍后重试");
|
||||
}else {
|
||||
ToastUtils.showShort("查询所有绑定路线失败:"+failMsg);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void commitSwitchLineId(int lineId){
|
||||
SweepersServiceManager.getInstance().resetStationStatus(mContext,lineId, new ISweepersServiceCallback<SweepersRoutesResponse>() {
|
||||
@Override
|
||||
public void onSuccess(SweepersRoutesResponse o) {
|
||||
if (mBusLinesCallback != null){
|
||||
mBusLinesCallback.onChangeLineIdSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail(String failMsg) {
|
||||
if (!NetworkUtils.isConnected(mContext)) {
|
||||
ToastUtils.showShort("网络异常,请稍后重试");
|
||||
}else {
|
||||
ToastUtils.showShort("切换路线失败:"+failMsg);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
package com.mogo.och.sweepers.net;
|
||||
import com.mogo.eagle.core.data.BaseData;
|
||||
import com.mogo.och.sweepers.bean.SweepersOperationStatusRequest;
|
||||
import com.mogo.och.sweepers.bean.SweepersOrdersResponse;
|
||||
import com.mogo.och.sweepers.bean.SweepersQueryLinesResponse;
|
||||
import com.mogo.och.sweepers.bean.SweepersRoutePlanningUpdateReqBean;
|
||||
import com.mogo.och.sweepers.bean.SweepersRoutesResponse;
|
||||
import com.mogo.och.sweepers.bean.CarHeartbeatReqBean;
|
||||
import com.mogo.och.sweepers.bean.SweepersQueryLineStationsRequest;
|
||||
import com.mogo.och.sweepers.bean.SweepersOperationStatusResponse;
|
||||
import com.mogo.och.sweepers.bean.QueryLeaveAwayPassengersRequest;
|
||||
import com.mogo.och.sweepers.bean.QueryLeaveAwayPassengersResponse;
|
||||
import com.mogo.och.sweepers.bean.SweepersResetDrivingLineRequest;
|
||||
import com.mogo.och.sweepers.bean.SweepersUpdateSiteStatusRequest;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import retrofit2.http.Body;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.Header;
|
||||
import retrofit2.http.Headers;
|
||||
import retrofit2.http.POST;
|
||||
import retrofit2.http.Query;
|
||||
|
||||
/**
|
||||
* 小巴车相关接口
|
||||
*
|
||||
* @author tongchenfei
|
||||
* <p>
|
||||
* wiki: http://wiki.zhidaohulian.com/pages/viewpage.action?pageId=48970072
|
||||
*/
|
||||
public interface ISweepersApiService {
|
||||
/**
|
||||
* 根据车机坐标获取所在区域全部站点信息
|
||||
*
|
||||
* @param request 请求参数
|
||||
* @return 接口返回数据
|
||||
*/
|
||||
@Headers( {"Content-Type:application/json;charset=UTF-8"} )
|
||||
// @POST( "/autopilot-car-hailing/line/v2/lineDataWithDriver/query" )
|
||||
@POST( "/autopilot-car-hailing/line/v2/driver/bus/lineDataWithDriver/query" )
|
||||
// @POST( "/mock/268/autopilot-car-hailing/bus/api/lineDataWithDriver/query" )
|
||||
Observable<SweepersRoutesResponse> querySiteByCoordinate(@Header ("appId") String appId, @Header("ticket") String ticket, @Body SweepersQueryLineStationsRequest request);
|
||||
|
||||
/**
|
||||
* 重置巴士路线: 点击小巴车tab 或者出车后会使用
|
||||
*
|
||||
* @param request 请求参数{"destLine":1,"sn":"F803EB2046PZD00229"} 这个接口是重置bus线路的, 不是重置线路中站点的
|
||||
* @return 返回值是重置后的车站列表
|
||||
*/
|
||||
@Headers( {"Content-Type:application/json;charset=UTF-8"} )
|
||||
// @POST( "/autopilot-car-hailing/car/v2/bus/drivingLine/reset" )
|
||||
@POST( "/autopilot-car-hailing/car/v2/driver/bus/drivingLine/reset" )
|
||||
// @POST( "/mock/268/autopilot-car-hailing/bus/api/drivingLine/reset" )
|
||||
Observable<SweepersRoutesResponse> resetStationStatus(@Header ("appId") String appId, @Header("ticket") String ticket, @Body SweepersResetDrivingLineRequest request);
|
||||
|
||||
/**
|
||||
* 离站,通知服务器
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@Headers({"Content-Type:application/json;charset=UTF-8"})
|
||||
// @POST("/autopilot-car-hailing/car/v2/bus/driving/away")
|
||||
@POST("/autopilot-car-hailing/car/v2/driver/bus/driving/away")
|
||||
// @POST("/mock/268/autopilot-car-hailing/bus/api/driving/away")
|
||||
Observable<SweepersRoutesResponse> leaveStation(@Header ("appId") String appId, @Header("ticket") String ticket, @Body SweepersUpdateSiteStatusRequest request);
|
||||
|
||||
/**
|
||||
* 到站 更新到站信息
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@Headers({"Content-type:application/json;charset=UTF-8"})
|
||||
// @POST("/autopilot-car-hailing/order/v2/bus/driving/attachSite")
|
||||
@POST("/autopilot-car-hailing/order/v2/driver/bus/driving/attachSite")
|
||||
// @POST("/mock/268/autopilot-car-hailing/bus/api/driving/attachSite")
|
||||
Observable< BaseData > arriveSiteStation(@Header ("appId") String appId,@Header("ticket") String ticket,@Body SweepersUpdateSiteStatusRequest request);
|
||||
|
||||
|
||||
/**
|
||||
* 到站查询下车乘客
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@Headers({"Content-type:application/json;charset=UTF-8"})
|
||||
// @POST("/autopilot-car-hailing/order/v2/bus/driving/siteArrivedOrders")
|
||||
@POST("/autopilot-car-hailing/order/v2/driver/bus/driving/siteArrivedOrders")
|
||||
// @POST("/mock/268/autopilot-car-hailing/bus/api/driving/siteArrivedOrders")
|
||||
Observable< QueryLeaveAwayPassengersResponse > queryStationLeaveAwayPassengers(@Header ("appId") String appId,@Header("ticket") String ticket,@Body QueryLeaveAwayPassengersRequest request);
|
||||
|
||||
/**
|
||||
* 出车
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@Headers( {"Content-type:application/json;charset=UTF-8"} )
|
||||
// @POST("/autopilot-car-hailing/car/v2/bus/startTakeOrder")
|
||||
@POST("/autopilot-car-hailing/car/v2/driver/bus/startTakeOrder")
|
||||
// @POST("/mock/268/autopilot-car-hailing/bus/api/startTakeOrder")
|
||||
Observable<BaseData> startTakeOrder(@Header ("appId") String appId,@Header("ticket") String ticket,@Body SweepersOperationStatusRequest request);
|
||||
|
||||
/**
|
||||
* 收车
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@Headers({"Content-type:application/json;charset=UTF-8"})
|
||||
// @POST("/autopilot-car-hailing/car/v2/bus/stopTakeOrder")
|
||||
@POST("/autopilot-car-hailing/car/v2/driver/bus/stopTakeOrder")
|
||||
// @POST("/mock/268/autopilot-car-hailing/bus/api/stopTakeOrder")
|
||||
Observable<BaseData> stopTakeOrder(@Header ("appId") String appId,@Header("ticket") String ticket,@Body SweepersOperationStatusRequest request);
|
||||
|
||||
/**
|
||||
* 查询小巴出车/收车状态
|
||||
* @param sn
|
||||
* @return
|
||||
*/
|
||||
@Headers({"Content-type:application/json;charset=UTF-8"})
|
||||
// @GET("/autopilot-car-hailing/car/v2/bus/takeOrderStatus/query")
|
||||
@GET("/autopilot-car-hailing/car/v2/driver/bus/takeOrderStatus/query")
|
||||
// @GET("/mock/268/autopilot-car-hailing/bus/api/takeOrderStatus/query")
|
||||
Observable<SweepersOperationStatusResponse> queryOperationStatus(@Header ("appId") String appId, @Header("ticket") String ticket, @Query("sn") String sn);
|
||||
|
||||
@Headers({"Content-type:application/json;charset=UTF-8"})
|
||||
// @GET("/autopilot-car-hailing/order/v2/bus/servicingOrders/query")
|
||||
@GET("/autopilot-car-hailing/order/v2/driver/bus/servicingOrders/query")
|
||||
// @GET("/mock/268/autopilot-car-hailing/bus/api/servicingOrders/query")
|
||||
Observable<SweepersOrdersResponse> queryBusOrders(@Header ("appId") String appId, @Header("ticket") String ticket, @Query("sn") String sn);
|
||||
|
||||
/**
|
||||
* 车机端上传心跳数据(只在出车状态时上传):包含高德坐标系经纬度
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
@Headers( {"Content-type:application/json;charset=UTF-8"} )
|
||||
// @POST( "/autopilot-car-hailing/location/v2/driver/heartbeat" )
|
||||
@POST( "/autopilot-car-hailing/location/v2/driver/bus/heartbeat" )
|
||||
Observable<BaseData> runCarHeartbeat(@Header ("appId") String appId,@Header("ticket") String ticket,@Body CarHeartbeatReqBean data);
|
||||
|
||||
/**
|
||||
* 查询车辆配置的所有路线
|
||||
* @param appId
|
||||
* @param ticket
|
||||
* @param sn
|
||||
* @return
|
||||
*/
|
||||
// @GET("/autopilot-car-hailing/line/v2/driver/bindLine/query")
|
||||
@GET("/autopilot-car-hailing/line/v2/driver/bus/bindLine/query")
|
||||
Observable<SweepersQueryLinesResponse> queryBusLines(@Header ("appId") String appId, @Header("ticket") String ticket, @Query("sn") String sn);
|
||||
|
||||
@Headers( {"Content-type:application/json;charset=UTF-8"} )
|
||||
@POST( "/autopilot-car-hailing/location/v2/driver/bus/saveLineCoordinate" )
|
||||
Observable<BaseData> updateOrderRoute(@Header ("appId") String appId, @Header("ticket") String ticket, @Body SweepersRoutePlanningUpdateReqBean data);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.mogo.och.sweepers.net;
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2021/10/20
|
||||
*/
|
||||
public interface ISweepersServiceCallback< T >{
|
||||
void onSuccess(T o);
|
||||
|
||||
void onFail(String failMsg);
|
||||
|
||||
default void onError() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
package com.mogo.och.sweepers.net;
|
||||
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
|
||||
import com.mogo.eagle.core.data.BaseData;
|
||||
import com.mogo.eagle.core.network.MoGoRetrofitFactory;
|
||||
import com.mogo.eagle.core.network.RequestOptions;
|
||||
import com.mogo.eagle.core.network.SubscribeImpl;
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
|
||||
import com.mogo.och.sweepers.bean.SweepersQueryLinesResponse;
|
||||
import com.mogo.och.sweepers.bean.SweepersRoutePlanningUpdateReqBean;
|
||||
import com.mogo.och.sweepers.bean.SweepersRoutesResponse;
|
||||
import com.mogo.och.sweepers.bean.CarHeartbeatReqBean;
|
||||
import com.mogo.och.sweepers.bean.SweepersOperationStatusRequest;
|
||||
import com.mogo.och.sweepers.bean.SweepersOperationStatusResponse;
|
||||
import com.mogo.och.sweepers.bean.SweepersOrdersResponse;
|
||||
import com.mogo.och.sweepers.bean.SweepersQueryLineStationsRequest;
|
||||
import com.mogo.och.sweepers.bean.SweepersResetDrivingLineRequest;
|
||||
import com.mogo.och.sweepers.bean.SweepersUpdateSiteStatusRequest;
|
||||
import com.mogo.och.sweepers.bean.QueryLeaveAwayPassengersRequest;
|
||||
import com.mogo.och.sweepers.bean.QueryLeaveAwayPassengersResponse;
|
||||
import com.mogo.och.sweepers.constant.SweepersConst;
|
||||
import com.mogo.och.sweepers.model.SweepersOrderModel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2021/10/20
|
||||
*/
|
||||
public class SweepersServiceManager {
|
||||
|
||||
private static final String TAG = SweepersServiceManager.class.getSimpleName();
|
||||
|
||||
private final ISweepersApiService mService;
|
||||
|
||||
private static final class SingletonHolder {
|
||||
private static final SweepersServiceManager INSTANCE = new SweepersServiceManager();
|
||||
}
|
||||
|
||||
public static SweepersServiceManager getInstance(){
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private SweepersServiceManager(){
|
||||
mService = MoGoRetrofitFactory.getInstance(SweepersConst.getBaseUrl()).create(ISweepersApiService.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询小巴车线路
|
||||
* @param context
|
||||
* @param callback
|
||||
*/
|
||||
public void queryBusRoutes(Context context, ISweepersServiceCallback<SweepersRoutesResponse> callback) {
|
||||
//获取当前高德坐标
|
||||
|
||||
mService.querySiteByCoordinate(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
|
||||
,MoGoAiCloudClientConfig.getInstance().getToken()
|
||||
, new SweepersQueryLineStationsRequest(SweepersOrderModel.getInstance().mLongitude
|
||||
, SweepersOrderModel.getInstance().mLatitude,true))
|
||||
.subscribeOn( Schedulers.io() ).observeOn( AndroidSchedulers.mainThread() )
|
||||
.subscribe( getSubscribeImpl(context,callback,"querySiteByCoordinate"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置线路站点
|
||||
* @param context
|
||||
* @param lineId
|
||||
* @param callback
|
||||
*/
|
||||
public void resetStationStatus(Context context, int lineId, ISweepersServiceCallback<SweepersRoutesResponse> callback){
|
||||
mService.resetStationStatus(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
|
||||
,MoGoAiCloudClientConfig.getInstance().getToken(),new SweepersResetDrivingLineRequest(lineId))
|
||||
.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(getSubscribeImpl(context,callback,"debugResetStationStatus"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 离站上报
|
||||
* @param context
|
||||
* @param seq
|
||||
* @param siteId
|
||||
* @param callback
|
||||
*/
|
||||
public void leaveStation(Context context, int seq, int siteId, ISweepersServiceCallback<SweepersRoutesResponse> callback){
|
||||
mService.leaveStation(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
|
||||
,MoGoAiCloudClientConfig.getInstance().getToken()
|
||||
,new SweepersUpdateSiteStatusRequest(seq,siteId, SweepersOrderModel.getInstance().mLongitude
|
||||
, SweepersOrderModel.getInstance().mLatitude))
|
||||
.subscribeOn( Schedulers.io() )
|
||||
.observeOn( AndroidSchedulers.mainThread() )
|
||||
.subscribe(getSubscribeImpl(context,callback,"leaveStation"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 到站更新站点状态
|
||||
* @param context
|
||||
* @param seq
|
||||
* @param siteId
|
||||
* @param callback
|
||||
*/
|
||||
public void arriveSiteStation(Context context, int seq, int siteId, ISweepersServiceCallback<BaseData> callback){
|
||||
mService.arriveSiteStation(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
|
||||
,MoGoAiCloudClientConfig.getInstance().getToken()
|
||||
,new SweepersUpdateSiteStatusRequest(seq,siteId
|
||||
, SweepersOrderModel.getInstance().mLongitude, SweepersOrderModel.getInstance().mLatitude))
|
||||
.subscribeOn( Schedulers.io() )
|
||||
.observeOn( AndroidSchedulers.mainThread() )
|
||||
.subscribe(getSubscribeImpl(context,callback,"leaveStation"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询下车乘客
|
||||
* @param context
|
||||
* @param seq
|
||||
* @param siteId
|
||||
* @param callback
|
||||
*/
|
||||
public void queryStationLeaveAwayPassengers(Context context, int seq, int siteId
|
||||
, ISweepersServiceCallback<QueryLeaveAwayPassengersResponse> callback){
|
||||
mService.queryStationLeaveAwayPassengers( MoGoAiCloudClientConfig.getInstance().getServiceAppId()
|
||||
,MoGoAiCloudClientConfig.getInstance().getToken(),new QueryLeaveAwayPassengersRequest(seq,siteId))
|
||||
.subscribeOn( Schedulers.io() )
|
||||
.observeOn( AndroidSchedulers.mainThread() )
|
||||
.subscribe(getSubscribeImpl(context,callback,"queryStationLeaveAwayPassengers"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 收车
|
||||
* @param context
|
||||
* @param callback
|
||||
*/
|
||||
public void stopTakeOrder(Context context, ISweepersServiceCallback<BaseData> callback){
|
||||
mService.stopTakeOrder(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
|
||||
,MoGoAiCloudClientConfig.getInstance().getToken()
|
||||
,new SweepersOperationStatusRequest(SweepersOrderModel.getInstance().mLongitude
|
||||
, SweepersOrderModel.getInstance().mLatitude))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(getSubscribeImpl(context,callback,"stopTakeOrder"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 出车
|
||||
* @param context
|
||||
* @param callback
|
||||
*/
|
||||
public void startTakeOrder(Context context, ISweepersServiceCallback<BaseData> callback){
|
||||
mService.startTakeOrder(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
|
||||
,MoGoAiCloudClientConfig.getInstance().getToken()
|
||||
,new SweepersOperationStatusRequest(SweepersOrderModel.getInstance().mLongitude
|
||||
, SweepersOrderModel.getInstance().mLatitude))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(getSubscribeImpl(context,callback,"startTakeOrder"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询出车/收车状态
|
||||
* @param context
|
||||
* @param callback
|
||||
*/
|
||||
public void queryOperationStatus(Context context, ISweepersServiceCallback<SweepersOperationStatusResponse> callback){
|
||||
mService.queryOperationStatus(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
|
||||
,MoGoAiCloudClientConfig.getInstance().getToken(),MoGoAiCloudClientConfig.getInstance().getSn())
|
||||
.subscribeOn( Schedulers.io() )
|
||||
.observeOn( AndroidSchedulers.mainThread() )
|
||||
.subscribe(getSubscribeImpl(context,callback,"queryOperationStatus"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询小巴车订单
|
||||
* @param context
|
||||
* @param callback
|
||||
*/
|
||||
public void queryBusOrders(Context context, ISweepersServiceCallback<SweepersOrdersResponse> callback){
|
||||
mService.queryBusOrders(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
|
||||
,MoGoAiCloudClientConfig.getInstance().getToken(),MoGoAiCloudClientConfig.getInstance().getSn())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(getSubscribeImpl(context,callback,"queryBusOrders"));
|
||||
}
|
||||
|
||||
public void queryBusLines(Context context, ISweepersServiceCallback<SweepersQueryLinesResponse> callback){
|
||||
mService.queryBusLines(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
|
||||
,MoGoAiCloudClientConfig.getInstance().getToken(),MoGoAiCloudClientConfig.getInstance().getSn())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(getSubscribeImpl(context,callback,"queryBusLines"));
|
||||
}
|
||||
|
||||
public void updateOrderRoute(Context context,int lineId, int startSiteId, int endSiteId
|
||||
, List< SweepersRoutePlanningUpdateReqBean.Result > points
|
||||
, ISweepersServiceCallback<BaseData> callback){
|
||||
mService.updateOrderRoute(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
|
||||
,MoGoAiCloudClientConfig.getInstance().getToken()
|
||||
,new SweepersRoutePlanningUpdateReqBean(MoGoAiCloudClientConfig.getInstance().getSn()
|
||||
,lineId,startSiteId,endSiteId, points))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(getSubscribeImpl(context,callback,"updateOrderRoute"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 车机端上传心跳数据(只在出车状态时上传):包含高德坐标系经纬度
|
||||
* @param context
|
||||
* @param lon
|
||||
* @param lat
|
||||
* @param callback
|
||||
*/
|
||||
public void runCarHeartbeat(Context context, double lon, double lat,
|
||||
ISweepersServiceCallback<BaseData> callback) {
|
||||
mService.runCarHeartbeat(MoGoAiCloudClientConfig.getInstance().getServiceAppId()
|
||||
,MoGoAiCloudClientConfig.getInstance().getToken(),new CarHeartbeatReqBean(
|
||||
MoGoAiCloudClientConfig.getInstance().getSn(), lon, lat))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(getSubscribeImpl(context, callback, "runCarHeartbeat"));
|
||||
}
|
||||
|
||||
private <T extends BaseData> SubscribeImpl getSubscribeImpl(Context context, ISweepersServiceCallback<T> callback, String apiName){
|
||||
return new SubscribeImpl<T>(RequestOptions.create(context)){
|
||||
@Override
|
||||
public void onSuccess(T o) {
|
||||
super.onSuccess(o);
|
||||
CallerLogger.INSTANCE.e(M_BUS + TAG,apiName + ": onSuccess() " + o.msg);
|
||||
if (callback != null) {
|
||||
callback.onSuccess(o);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(String message, int code) {
|
||||
super.onError(message, code);
|
||||
CallerLogger.INSTANCE.e(M_BUS + TAG,apiName + ": onError() " +"msg="+ message+" code="+code);
|
||||
if (callback != null) {
|
||||
callback.onFail("msg="+ message+" code="+code);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
super.onError(e);
|
||||
CallerLogger.INSTANCE.e(M_BUS + TAG,apiName + ": onError() " +" e="+e.getMessage());
|
||||
if (callback != null) {
|
||||
callback.onFail(e.getMessage());
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.mogo.och.sweepers.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.sweepers.bean.SweepersQueryLinesResponse;
|
||||
import com.mogo.och.sweepers.callback.ISweepersLinesCallback;
|
||||
import com.mogo.och.sweepers.model.SweepersLineModel;
|
||||
import com.mogo.och.sweepers.model.SweepersOrderModel;
|
||||
import com.mogo.och.sweepers.ui.SweepersSwitchLineView;
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2022/2/9
|
||||
*/
|
||||
public class SweepersLinePresenter extends Presenter<SweepersSwitchLineView> implements ISweepersLinesCallback {
|
||||
|
||||
public SweepersLinePresenter(SweepersSwitchLineView view) {
|
||||
super(view);
|
||||
SweepersLineModel.getInstance().init();
|
||||
SweepersOrderModel.getInstance().init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@NonNull LifecycleOwner owner) {
|
||||
super.onCreate(owner);
|
||||
initListener();
|
||||
}
|
||||
|
||||
private void initListener() {
|
||||
SweepersLineModel.getInstance().setBusLinesCallback(this);
|
||||
}
|
||||
|
||||
private void runOnUIThread( Runnable executor ) {
|
||||
if ( executor == null ) {
|
||||
return;
|
||||
}
|
||||
if ( Looper.myLooper() != Looper.getMainLooper() ) {
|
||||
UiThreadHandler.post( executor );
|
||||
} else {
|
||||
executor.run();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBusLinesChange(SweepersQueryLinesResponse lines) {
|
||||
runOnUIThread(() -> mView.onBusLinesChange(lines));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeLineIdSuccess() {
|
||||
runOnUIThread(() -> mView.onChangeLineIdSuccess());
|
||||
}
|
||||
|
||||
public void queryBusLines(){
|
||||
SweepersLineModel.getInstance().queryBusLines();
|
||||
}
|
||||
|
||||
public void commitSwitchLineId(int lineId){
|
||||
SweepersLineModel.getInstance().commitSwitchLineId(lineId);
|
||||
}
|
||||
|
||||
public void removeListener(){
|
||||
SweepersLineModel.getInstance().setBusLinesCallback(null);
|
||||
}
|
||||
|
||||
public void queryBusRoutes(){
|
||||
SweepersOrderModel.getInstance().querySweepersRoutes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy(@NonNull LifecycleOwner owner) {
|
||||
super.onDestroy(owner);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.mogo.och.sweepers.presenter;
|
||||
|
||||
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS;
|
||||
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
|
||||
import com.mogo.och.sweepers.constant.SweepersConst;
|
||||
import com.mogo.och.sweepers.model.SweepersOrderModel;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
/**
|
||||
* Created on 2021/11/22
|
||||
*
|
||||
* 管理轮询逻辑(订单轮询、新单轮询、新单抢单结果轮询等等)
|
||||
*/
|
||||
public class SweepersModelLoopManager {
|
||||
|
||||
private static final String TAG = SweepersModelLoopManager.class.getSimpleName();
|
||||
|
||||
private static final class SingletonHolder {
|
||||
private static final SweepersModelLoopManager INSTANCE = new SweepersModelLoopManager();
|
||||
}
|
||||
|
||||
public static SweepersModelLoopManager getInstance() {
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private Disposable mHeartbeatDisposable; //心跳轮询
|
||||
|
||||
public void startHeartbeatLoop() {
|
||||
if (mHeartbeatDisposable != null && !mHeartbeatDisposable.isDisposed()) {
|
||||
return;
|
||||
}
|
||||
CallerLogger.INSTANCE.i(M_BUS + TAG, "startHeartbeatLoop()");
|
||||
mHeartbeatDisposable = Observable.interval(SweepersConst.LOOP_DELAY,
|
||||
SweepersConst.LOOP_PERIOD_60S, TimeUnit.MILLISECONDS)
|
||||
.map((aLong -> aLong + 1))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(aLong -> SweepersOrderModel.getInstance().runCarHeartbeat());
|
||||
}
|
||||
|
||||
public void stopHeartbeatLoop() {
|
||||
if (mHeartbeatDisposable != null) {
|
||||
CallerLogger.INSTANCE.i(M_BUS + TAG, "stopHeartbeatLoop()");
|
||||
mHeartbeatDisposable.dispose();
|
||||
mHeartbeatDisposable = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
package com.mogo.och.sweepers.presenter;
|
||||
|
||||
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS;
|
||||
|
||||
import android.location.Location;
|
||||
import android.os.Looper;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
|
||||
import com.mogo.commons.mvp.Presenter;
|
||||
import com.mogo.eagle.core.data.autopilot.AutopilotStatusInfo;
|
||||
import com.mogo.eagle.core.data.config.FunctionBuildConfig;
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener;
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager;
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
|
||||
import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
|
||||
import com.mogo.och.sweepers.bean.SweepersStationBean;
|
||||
import com.mogo.och.sweepers.callback.ICarOperationStatusCallback;
|
||||
import com.mogo.och.sweepers.callback.ISweepersControllerStatusCallback;
|
||||
import com.mogo.och.sweepers.callback.IRefreshSweepersStationsCallback;
|
||||
import com.mogo.och.sweepers.callback.ISlidePannelHideCallback;
|
||||
import com.mogo.och.sweepers.fragment.SweepersFragment;
|
||||
import com.mogo.och.sweepers.model.SweepersOrderModel;
|
||||
import com.mogo.och.sweepers.util.SweepersTrajectoryManager;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import mogo.telematics.pad.MessagePad;
|
||||
import mogo_msg.MogoReportMsg;
|
||||
import system_master.SystemStatusInfo;
|
||||
|
||||
/**
|
||||
* 网约车小巴
|
||||
*
|
||||
* @author tongchenfei
|
||||
*/
|
||||
public class SweepersPresenter extends Presenter<SweepersFragment>
|
||||
implements ICarOperationStatusCallback, IRefreshSweepersStationsCallback, ISlidePannelHideCallback
|
||||
, IMoGoAutopilotStatusListener, ISweepersControllerStatusCallback {
|
||||
|
||||
private static final String TAG = "BusPresenter";
|
||||
|
||||
private int currentAutopilotStatus = -1;
|
||||
private List<SweepersStationBean> mStationList = new ArrayList<>();
|
||||
private int mCurrentStation = 0;
|
||||
private boolean isRestartAutopilot = false;
|
||||
|
||||
public SweepersPresenter(SweepersFragment view) {
|
||||
super(view);
|
||||
//2021.11.1 鹰眼架构整合,由IMoGoAutopilotStatusListener逐步替代IMogoAdasOCHCallback接口
|
||||
CallerAutoPilotStatusListenerManager.INSTANCE.addListener(TAG, this);
|
||||
SweepersOrderModel.getInstance().init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@NonNull LifecycleOwner owner) {
|
||||
super.onCreate(owner);
|
||||
SweepersOrderModel.getInstance().queryOperationStatus();
|
||||
SweepersOrderModel.getInstance().querySweepersRoutes();
|
||||
initModelListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy(@NonNull LifecycleOwner owner) {
|
||||
super.onDestroy(owner);
|
||||
SweepersOrderModel.getInstance().release();
|
||||
releaseListener();
|
||||
}
|
||||
|
||||
public void initModelListener() {
|
||||
SweepersOrderModel.getInstance().setCarOperationStatusCallback(this);
|
||||
SweepersOrderModel.getInstance().setRefreshBusStationsCallback(this);
|
||||
SweepersOrderModel.getInstance().setSlidePannelHideCallback(this);
|
||||
SweepersOrderModel.getInstance().setControllerStatusCallback(this);
|
||||
}
|
||||
|
||||
public void releaseListener() {
|
||||
SweepersOrderModel.getInstance().setCarOperationStatusCallback(null);
|
||||
SweepersOrderModel.getInstance().setRefreshBusStationsCallback(null);
|
||||
SweepersOrderModel.getInstance().setSlidePannelHideCallback(null);
|
||||
SweepersOrderModel.getInstance().setControllerStatusCallback(null);
|
||||
}
|
||||
|
||||
public void querySweepersRoutes() {
|
||||
SweepersOrderModel.getInstance().querySweepersRoutes();
|
||||
}
|
||||
|
||||
public void debugResetStationStatus() {
|
||||
SweepersOrderModel.getInstance().debugResetStationStatus();
|
||||
}
|
||||
|
||||
public void autoDriveToNextStation(boolean isRestart) {
|
||||
currentAutopilotStatus = -1;
|
||||
SweepersOrderModel.getInstance().autoDriveToNextStation(isRestart);
|
||||
isRestartAutopilot = false;
|
||||
}
|
||||
|
||||
public void restartAutopilot() {
|
||||
if (SweepersOrderModel.getInstance().isGoingToNextStation()){
|
||||
currentAutopilotStatus = -1;
|
||||
SweepersOrderModel.getInstance().restartAutopilot();
|
||||
isRestartAutopilot = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void onChangeOperationStatus() {
|
||||
SweepersOrderModel.getInstance().onChangeOperationStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeOperationStatus(boolean changeStatus) {
|
||||
if (mView != null) {
|
||||
runOnUIThread(() -> mView.changeOperationStatus(changeStatus));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshBusStations(String lineName,List<SweepersStationBean> stationList
|
||||
, int currentStation, int nextStation, boolean isArrived) {
|
||||
mStationList.clear();
|
||||
mStationList.addAll(stationList);
|
||||
mCurrentStation = currentStation;
|
||||
// functionDemoModeChange();
|
||||
CallerLogger.INSTANCE.d(M_BUS + "BusOrderModel =", " mCurrentStation =" + mCurrentStation);
|
||||
if (mView != null) {
|
||||
runOnUIThread(() -> mView.refreshSweepersStations(lineName,
|
||||
stationList, currentStation, nextStation, isArrived));
|
||||
}
|
||||
}
|
||||
|
||||
private void functionDemoModeChange() {
|
||||
// CallerLogger.INSTANCE.d(M_BUS + "BusOrderModel ="," functionDemoModeChange ="+mCurrentStation);
|
||||
if (FunctionBuildConfig.isDemoMode
|
||||
&& ((mCurrentStation > 0 && mCurrentStation < mStationList.size() - 1)
|
||||
|| ((mCurrentStation == 0 || mCurrentStation == mStationList.size() - 1)
|
||||
&& SweepersOrderModel.getInstance().isGoingToNextStation()))) {
|
||||
runOnUIThread(() -> mView.onAutopilotStatusChanged(
|
||||
IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideSlidePanel() {
|
||||
if (mView != null) {
|
||||
runOnUIThread(() -> mView.hideSlidePanel());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAutopilotArriveAtStation(MessagePad.ArrivalNotification arrivalNotification) {
|
||||
SweepersOrderModel.getInstance().onArriveAt(arrivalNotification);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAutopilotSNRequest() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAutopilotStatusResponse(@NotNull AutopilotStatusInfo autopilotStatusInfo) {
|
||||
if (autopilotStatusInfo == null) return;
|
||||
int state = autopilotStatusInfo.getState();
|
||||
// CallerLogger.INSTANCE.d(M_BUS + TAG, "onStateChange: " + state + "currentAutopilotStatus = " + currentAutopilotStatus);
|
||||
switch (state) {
|
||||
case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE:
|
||||
if (currentAutopilotStatus != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE) {
|
||||
if (currentAutopilotStatus == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) {//2-->1语音提示
|
||||
// AIAssist.getInstance( getContext() ).speakTTSVoice( "已进入人工驾驶模式" );
|
||||
}
|
||||
currentAutopilotStatus = IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE;
|
||||
// 设置UI【自动驾驶】按钮是否展示
|
||||
runOnUIThread(() -> mView.onAutopilotEnableChange(true));
|
||||
if (SweepersOrderModel.getInstance().isGoingToNextStation()) {
|
||||
runOnUIThread(() -> mView.hideSlidePanel());
|
||||
}
|
||||
if (FunctionBuildConfig.isDemoMode
|
||||
&& (
|
||||
(mCurrentStation > 0 && mCurrentStation < mStationList.size() - 1)
|
||||
|| (
|
||||
(mCurrentStation == 0 || mCurrentStation == mStationList.size() - 1)
|
||||
&& SweepersOrderModel.getInstance().isGoingToNextStation()
|
||||
)
|
||||
)
|
||||
) {
|
||||
CallerLogger.INSTANCE.d(M_BUS + "BusOrderModel=", "有美化功能");
|
||||
return;
|
||||
}
|
||||
// 改变UI自动驾驶状态
|
||||
runOnUIThread(() -> mView.onAutopilotStatusChanged(currentAutopilotStatus));
|
||||
}
|
||||
break;
|
||||
case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING:
|
||||
if (currentAutopilotStatus != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) {
|
||||
currentAutopilotStatus = IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING;
|
||||
// 改变UI自动驾驶状态
|
||||
runOnUIThread(() -> mView.onAutopilotStatusChanged(currentAutopilotStatus));
|
||||
SweepersOrderModel.getInstance().triggerStartServiceEvent(
|
||||
isRestartAutopilot, true);
|
||||
}
|
||||
break;
|
||||
case IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE:
|
||||
if (currentAutopilotStatus != IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE) {
|
||||
if (currentAutopilotStatus == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) {//2-->0语音提示
|
||||
// AIAssist.getInstance( getContext() ).speakTTSVoice( "自动驾驶已停止,请人工接管" );
|
||||
}
|
||||
currentAutopilotStatus = IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE;
|
||||
if (FunctionBuildConfig.isDemoMode
|
||||
&& (
|
||||
(mCurrentStation > 0 && mCurrentStation < mStationList.size() - 1)
|
||||
|| (
|
||||
(mCurrentStation == 0 || mCurrentStation == mStationList.size() - 1)
|
||||
&& SweepersOrderModel.getInstance().isGoingToNextStation()
|
||||
)
|
||||
)
|
||||
) {
|
||||
CallerLogger.INSTANCE.d(M_BUS + "BusOrderModel=", "有美化功能");
|
||||
return;
|
||||
}
|
||||
runOnUIThread(() -> {
|
||||
mView.onAutopilotStatusChanged(currentAutopilotStatus);
|
||||
});
|
||||
}
|
||||
break;
|
||||
default:
|
||||
runOnUIThread(() -> mView.onAutopilotEnableChange(false));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVRModeChanged(boolean isVRMode) {
|
||||
runOnUIThread(() -> mView.onVRModeChanged(isVRMode));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCarLocationChanged(Location location) {
|
||||
if (null != location) {
|
||||
runOnUIThread(() -> mView.updateSpeedView(location.getSpeed()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startOpenAutopilot() {
|
||||
//非美化模式下启动动画
|
||||
runOnUIThread(() -> mView.startAutopilotAnimation());
|
||||
}
|
||||
|
||||
private void runOnUIThread(Runnable executor) {
|
||||
if (executor == null) {
|
||||
return;
|
||||
}
|
||||
if (Looper.myLooper() != Looper.getMainLooper()) {
|
||||
UiThreadHandler.post(executor);
|
||||
} else {
|
||||
executor.run();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试使用
|
||||
*
|
||||
* @param status
|
||||
*/
|
||||
public void debugAutoPilotStatus(int status) {
|
||||
AutopilotStatusInfo info = new AutopilotStatusInfo();
|
||||
info.setState(status);
|
||||
onAutopilotStatusResponse(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAutopilotGuardian(MogoReportMsg.MogoReportMessage guardianInfo) {
|
||||
SweepersTrajectoryManager.getInstance().onAutopilotGuardian(guardianInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAutopilotIpcConnectStatusChanged(int status, @Nullable String reason) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAutopilotStatusRespByQuery(@NonNull SystemStatusInfo.StatusInfo status) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.mogo.och.sweepers.receiver;
|
||||
|
||||
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
|
||||
import com.mogo.och.sweepers.constant.SweepersConst;
|
||||
|
||||
/**
|
||||
* 测试小巴车的场景
|
||||
*
|
||||
* @author donghongyu
|
||||
* @date 4/26/21 12:08 PM
|
||||
*/
|
||||
public class TestSweepersBroadcastReceiver extends BroadcastReceiver {
|
||||
private static final String TAG = "TestBusBroadcastReceiver";
|
||||
|
||||
private Context mContext;
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
try {
|
||||
this.mContext = context;
|
||||
int sceneType = intent.getIntExtra(SweepersConst.BROADCAST_TEST_SWEEPERS_CONTROL_TYPE_EXTRA_KEY, 0);
|
||||
CallerLogger.INSTANCE.d(M_BUS + TAG, "sceneType:" + sceneType);
|
||||
|
||||
// 分发场景
|
||||
dispatchSceneTest(sceneType);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void dispatchSceneTest(int sceneType) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
package com.mogo.och.sweepers.ui;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.graphics.Point;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.mogo.commons.mvp.MvpActivity;
|
||||
import com.mogo.eagle.core.utilcode.util.ToastUtils;
|
||||
import com.mogo.och.sweepers.R;
|
||||
import com.mogo.och.sweepers.bean.SweepersQueryLinesResponse;
|
||||
import com.mogo.och.sweepers.presenter.SweepersLinePresenter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2022/2/8
|
||||
*/
|
||||
public class SweepersSwitchLineActivity extends MvpActivity<SweepersSwitchLineView, SweepersLinePresenter>
|
||||
implements View.OnClickListener, SweepersSwitchLineView {
|
||||
|
||||
private ImageView mClose;
|
||||
private ConstraintLayout mNoDatasView;
|
||||
private RecyclerView mLinesListView;
|
||||
private TextView mLineCommitBtn;
|
||||
private SwitchLineAdapter mAdapter;
|
||||
private List<SweepersQueryLinesResponse.Result> mData = new ArrayList<>();
|
||||
private int mSelectLineId = -1;
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.activity_sweepers_switch_line;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected SweepersLinePresenter createPresenter() {
|
||||
return new SweepersLinePresenter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initViews() {
|
||||
initWH();
|
||||
initView();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
initDatas();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化view
|
||||
*/
|
||||
private void initView() {
|
||||
mClose = findViewById(R.id.switch_line_close);
|
||||
mClose.setOnClickListener(this);
|
||||
mNoDatasView = findViewById(R.id.no_order_data_view);
|
||||
|
||||
mLineCommitBtn = findViewById(R.id.switch_line_btn_commit);
|
||||
mLineCommitBtn.setOnClickListener(this);
|
||||
|
||||
mLinesListView = findViewById(R.id.switch_line_rv);
|
||||
mLinesListView.setLayoutManager(new LinearLayoutManager(this));
|
||||
mAdapter = new SwitchLineAdapter(getApplicationContext(),mData);
|
||||
mLinesListView.setAdapter(mAdapter);
|
||||
//设置item 点击事件
|
||||
mAdapter.setOnLineItemClickListener(new LineItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(int position) {
|
||||
if (mData.size() > position && !TextUtils.isEmpty(mData.get(position).startSiteName )
|
||||
&& !TextUtils.isEmpty(mData.get(position).endSiteName)){
|
||||
mSelectLineId = mData.get(position).lineId;
|
||||
}else {
|
||||
mSelectLineId = -1;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置布局宽高
|
||||
*/
|
||||
private void initWH() {
|
||||
|
||||
Window window = getWindow();
|
||||
|
||||
WindowManager.LayoutParams params = window.getAttributes();
|
||||
WindowManager windowManager = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
|
||||
Point point = new Point();
|
||||
windowManager.getDefaultDisplay().getSize(point);//用于获取屏幕高度
|
||||
|
||||
params.width = (int)(point.x * 0.375);
|
||||
params.height = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
window.setAttributes(params);
|
||||
window.setGravity(Gravity.LEFT|Gravity.BOTTOM);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化数据
|
||||
*/
|
||||
private void initDatas() {
|
||||
mPresenter.queryBusLines();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询返回绑定路线集合
|
||||
* @param data
|
||||
*/
|
||||
@Override
|
||||
public void onBusLinesChange(SweepersQueryLinesResponse data){
|
||||
if (null == data){
|
||||
showNoData(true);
|
||||
return;
|
||||
}
|
||||
if (data.data != null && data.data.size() > 0){
|
||||
showNoData(false);
|
||||
mData.clear();
|
||||
mData.addAll(data.data);
|
||||
mAdapter.notifyDataSetChanged();
|
||||
changeCommitBtnBg();
|
||||
}else {
|
||||
showNoData(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据路线选中情况设置提交按钮样式
|
||||
*/
|
||||
private void changeCommitBtnBg() {
|
||||
for (int i=0; i<mData.size();i++){
|
||||
if (mData.get(i).choose == 1){
|
||||
mLineCommitBtn.setBackgroundResource(R.drawable.sweepers_switch_line_btn_commit);
|
||||
mLineCommitBtn.setTextColor(getResources().getColor(R.color.sweepers_white));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeLineIdSuccess(){
|
||||
ToastUtils.showLong(getResources().getString(R.string.sweepers_change_line_commit_tip_s));
|
||||
mPresenter.queryBusRoutes();
|
||||
if (mAdapter != null){
|
||||
mAdapter.setOnLineItemClickListener(null);
|
||||
}
|
||||
mPresenter.removeListener();
|
||||
finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* 有无数据UI显示
|
||||
* @param b
|
||||
*/
|
||||
private void showNoData(boolean b) {
|
||||
if (b){
|
||||
mLinesListView.setVisibility(View.GONE);
|
||||
mLineCommitBtn.setVisibility(View.GONE);
|
||||
mNoDatasView.setVisibility(View.VISIBLE);
|
||||
}else {
|
||||
mLinesListView.setVisibility(View.VISIBLE);
|
||||
mLineCommitBtn.setVisibility(View.VISIBLE);
|
||||
mNoDatasView.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
//关闭dialog
|
||||
if (v.getId() == R.id.switch_line_close){
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
//切换路线提交
|
||||
if (v.getId() == R.id.switch_line_btn_commit){
|
||||
if (mSelectLineId > -1){
|
||||
mPresenter.commitSwitchLineId(mSelectLineId);
|
||||
}else {
|
||||
finish();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* 路线列表adapter
|
||||
*/
|
||||
static class SwitchLineAdapter extends RecyclerView.Adapter<SwitchLineViewHolder>{
|
||||
|
||||
private Context mContext;
|
||||
private List<SweepersQueryLinesResponse.Result> mData;
|
||||
// RecyclerView设置点击事件
|
||||
private LineItemClickListener mItemClickListener ;
|
||||
private int clickPos = -1;
|
||||
|
||||
public SwitchLineAdapter(Context context, List<SweepersQueryLinesResponse.Result> data){
|
||||
mContext = context;
|
||||
mData = data;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public SwitchLineViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(mContext).inflate(R.layout.sweepers_switch_line_list_item
|
||||
,parent,false);
|
||||
SwitchLineViewHolder viewHolder = new SwitchLineViewHolder(view);
|
||||
return viewHolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull SwitchLineViewHolder holder, @SuppressLint("RecyclerView") int position) {
|
||||
SweepersQueryLinesResponse.Result line = mData.get(position);
|
||||
holder.lineName.setText(mContext.getString(R.string.sweepers_switch_line_name)+" "+line.name);
|
||||
holder.lineStartName.setText(mContext.getString(R.string.sweepers_line_start)+" "+line.startSiteName);
|
||||
holder.lineEndName.setText(mContext.getString(R.string.sweepers_line_end)+" "+line.endSiteName);
|
||||
|
||||
//设置item点击事件
|
||||
holder.itemView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (mItemClickListener != null){
|
||||
mItemClickListener.onItemClick(position);
|
||||
clickPos = position;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
});
|
||||
//选中绑定
|
||||
if (clickPos > -1){
|
||||
if (clickPos == position){
|
||||
holder.selectIv.setImageResource(R.drawable.sweepers_selected_btn);
|
||||
}else {
|
||||
holder.selectIv.setImageResource(R.drawable.sweepers_unselect_btn);
|
||||
}
|
||||
}else {
|
||||
if (line.choose == 1){//1:绑定 2:未绑定 默认绑定
|
||||
if (mItemClickListener != null) {
|
||||
mItemClickListener.onItemClick(position);
|
||||
}
|
||||
holder.selectIv.setImageResource(R.drawable.sweepers_selected_btn);
|
||||
}else {
|
||||
holder.selectIv.setImageResource(R.drawable.sweepers_unselect_btn);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mData.size();
|
||||
}
|
||||
public void setOnLineItemClickListener(LineItemClickListener itemClickListener){
|
||||
this.mItemClickListener = itemClickListener ;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static class SwitchLineViewHolder extends RecyclerView.ViewHolder{
|
||||
|
||||
private ImageView selectIv;
|
||||
private TextView lineName; //线路名称
|
||||
private TextView lineStartName; //起点
|
||||
private TextView lineEndName; //终点
|
||||
|
||||
public SwitchLineViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
selectIv = itemView.findViewById(R.id.switch_line_item_select_iv);
|
||||
lineName = itemView.findViewById(R.id.switch_line_name);
|
||||
lineStartName = itemView.findViewById(R.id.switch_line_start_station);
|
||||
lineEndName = itemView.findViewById(R.id.switch_line_end_station);
|
||||
}
|
||||
}
|
||||
|
||||
public interface LineItemClickListener {
|
||||
void onItemClick(int position) ;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.mogo.och.sweepers.ui;
|
||||
|
||||
import com.mogo.commons.mvp.IView;
|
||||
import com.mogo.och.sweepers.bean.SweepersQueryLinesResponse;
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2022/2/10
|
||||
*/
|
||||
public interface SweepersSwitchLineView extends IView {
|
||||
|
||||
void onBusLinesChange(SweepersQueryLinesResponse data);
|
||||
void onChangeLineIdSuccess();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
package com.mogo.och.sweepers.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.mogo.eagle.core.function.api.hmi.view.IViewTrafficLight;
|
||||
import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
|
||||
import com.mogo.och.sweepers.R;
|
||||
import com.mogo.och.common.module.wigets.OCHGradientTextView;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Bus司机端:红绿灯view
|
||||
*
|
||||
* Created on 2022/3/29
|
||||
*/
|
||||
public class SweepersTrafficLightView extends IViewTrafficLight {
|
||||
|
||||
private ImageView mLightIconIV;
|
||||
private OCHGradientTextView mLightTimeTV;
|
||||
private int mCurrentLightId;
|
||||
|
||||
public SweepersTrafficLightView(@Nullable Context context) {
|
||||
this(context, null, 0);
|
||||
}
|
||||
|
||||
public SweepersTrafficLightView(@Nullable Context context, @Nullable AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public SweepersTrafficLightView(@Nullable Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context);
|
||||
}
|
||||
|
||||
private void init(Context context) {
|
||||
LayoutInflater.from(context).inflate(R.layout.sweepers_traffic_light_view, this, true);
|
||||
mLightIconIV = findViewById(R.id.sweepers_traffic_light_iv);
|
||||
mLightTimeTV = findViewById(R.id.sweepers_traffic_light_time_tv);
|
||||
}
|
||||
|
||||
/**
|
||||
* 展示红绿灯预警
|
||||
*
|
||||
* @param checkLightId 0-都是默认,1-红,2-黄,3-绿
|
||||
* @param lightSource 1:云端下发;2:自车感知
|
||||
*/
|
||||
@Override
|
||||
public void showWarningTrafficLight(int checkLightId,int lightSource) {
|
||||
super.showWarningTrafficLight(checkLightId,lightSource);
|
||||
mCurrentLightId = checkLightId;
|
||||
updateTrafficLightIcon(checkLightId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭红绿灯预警展示,并重制灯态
|
||||
*/
|
||||
@Override
|
||||
public void disableWarningTrafficLight() {
|
||||
super.disableWarningTrafficLight();
|
||||
UiThreadHandler.post(() -> {
|
||||
mCurrentLightId = 0;
|
||||
SweepersTrafficLightView.this.setVisibility(GONE);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param redNum 红灯倒计时
|
||||
* @param yellowNum 黄灯倒计时
|
||||
* @param greenNum 绿灯倒计时
|
||||
*/
|
||||
@Override
|
||||
public void changeCountdownTrafficLightNum(int redNum, int yellowNum, int greenNum) {
|
||||
super.changeCountdownTrafficLightNum(redNum, yellowNum, greenNum);
|
||||
switch (mCurrentLightId) {
|
||||
case 1:
|
||||
changeCountdownRed(redNum);
|
||||
break;
|
||||
case 2:
|
||||
changeCountdownYellow(yellowNum);
|
||||
break;
|
||||
case 3:
|
||||
changeCountdownGreen(greenNum);
|
||||
break;
|
||||
default:
|
||||
UiThreadHandler.post(() -> {
|
||||
mLightTimeTV.setText("");
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeCountdownRed(int redNum) {
|
||||
super.changeCountdownRed(redNum);
|
||||
UiThreadHandler.post(() -> {
|
||||
if (redNum > 0) {
|
||||
mLightTimeTV.setVertrial(true);
|
||||
mLightTimeTV.setmColorList(new int[]{getResources().getColor(R.color.sweepers_traffic_light_red_color_up),
|
||||
getResources().getColor(R.color.sweepers_traffic_light_red_color_down)});
|
||||
mLightTimeTV.setText(String.valueOf(redNum));
|
||||
} else {
|
||||
mLightTimeTV.setText("");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeCountdownGreen(int greenNum) {
|
||||
super.changeCountdownGreen(greenNum);
|
||||
UiThreadHandler.post(() -> {
|
||||
if (greenNum > 0) {
|
||||
mLightTimeTV.setVertrial(true);
|
||||
mLightTimeTV.setmColorList(new int[]{getResources().getColor(R.color.sweepers_traffic_light_green_color_up),
|
||||
getResources().getColor(R.color.sweepers_traffic_light_green_color_down)});
|
||||
mLightTimeTV.setText(String.valueOf(greenNum));
|
||||
} else {
|
||||
mLightTimeTV.setText("");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeCountdownYellow(int yellowNum) {
|
||||
super.changeCountdownYellow(yellowNum);
|
||||
UiThreadHandler.post(() -> {
|
||||
if (yellowNum > 0) {
|
||||
mLightTimeTV.setVertrial(true);
|
||||
mLightTimeTV.setmColorList(new int[]{getResources().getColor(R.color.sweepers_traffic_light_yellow_color_up),
|
||||
getResources().getColor(R.color.sweepers_traffic_light_yellow_color_down)});
|
||||
mLightTimeTV.setText(String.valueOf(yellowNum));
|
||||
} else {
|
||||
mLightTimeTV.setText("");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新红绿灯icon
|
||||
*
|
||||
* @param lightId 0-都是默认,1-红,2-黄,3-绿
|
||||
*/
|
||||
private void updateTrafficLightIcon(int lightId) {
|
||||
UiThreadHandler.post(() -> {
|
||||
switch (lightId) {
|
||||
case 1:
|
||||
mLightIconIV.setBackgroundResource(R.drawable.sweepers_light_red_nor);
|
||||
SweepersTrafficLightView.this.setVisibility(VISIBLE);
|
||||
break;
|
||||
case 2:
|
||||
mLightIconIV.setBackgroundResource(R.drawable.sweepers_lightyellow_nor);
|
||||
SweepersTrafficLightView.this.setVisibility(VISIBLE);
|
||||
break;
|
||||
case 3:
|
||||
mLightIconIV.setBackgroundResource(R.drawable.sweepers_light_green_nor);
|
||||
SweepersTrafficLightView.this.setVisibility(VISIBLE);
|
||||
break;
|
||||
default:
|
||||
SweepersTrafficLightView.this.setVisibility(GONE);
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.mogo.och.sweepers.util;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig;
|
||||
import com.mogo.commons.debug.DebugConfig;
|
||||
import com.mogo.eagle.core.data.app.AppConfigInfo;
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener;
|
||||
import com.mogo.eagle.core.function.call.analytics.AnalyticsManager;
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager;
|
||||
import com.mogo.eagle.core.utilcode.util.DateTimeUtils;
|
||||
import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
|
||||
import com.mogo.och.sweepers.constant.SweepersConst;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* OCH sweepers埋点工具
|
||||
*
|
||||
* Created on 2022/3/24
|
||||
*/
|
||||
public class SweepersAnalyticsManager {
|
||||
|
||||
private static final class SingletonHolder {
|
||||
private static final SweepersAnalyticsManager INSTANCE = new SweepersAnalyticsManager();
|
||||
}
|
||||
|
||||
public static SweepersAnalyticsManager getInstance() {
|
||||
return SweepersAnalyticsManager.SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private String mStartAutopilotKey;
|
||||
private HashMap<String, Object> mStartAutopilotParams = new HashMap<>();
|
||||
|
||||
private Runnable startAutopilotRunnable = () -> {
|
||||
// 15s内未开启,上报失败埋点
|
||||
mStartAutopilotParams.put(SweepersConst.EVENT_PARAM_START_RESULT
|
||||
, CallerAutoPilotStatusListenerManager.INSTANCE.getAutoPilotStatusInfo().getState() ==
|
||||
IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING);
|
||||
AnalyticsManager.INSTANCE.track(mStartAutopilotKey, mStartAutopilotParams);
|
||||
};
|
||||
|
||||
/**
|
||||
* 触发'开启自动驾驶'埋点流程
|
||||
* 开启自动驾驶,15s内成功则发送成功埋点,否则发送失败埋点
|
||||
* @param restart false(点击'滑动出发'启动)/true(接管后点击'自动驾驶'按钮启动)
|
||||
* @param send 是否直接发送埋点(15s内开启成功则直接发送成功埋点)
|
||||
*/
|
||||
public void triggerStartAutopilotEvent(
|
||||
boolean restart, boolean send, String startName, String endName, int lineId) {
|
||||
mStartAutopilotKey = restart ?
|
||||
SweepersConst.EVENT_KEY_RESTART_AUTOPILOT : SweepersConst.EVENT_KEY_START_SERVICE;
|
||||
String sn = MoGoAiCloudClientConfig.getInstance().getSn();
|
||||
String plateNum = AppConfigInfo.INSTANCE.getPlateNumber();
|
||||
String dateTime = DateTimeUtils.getTimeText(
|
||||
System.currentTimeMillis(), DateTimeUtils.yyyy_MM_dd_HH_mm_ss);
|
||||
|
||||
mStartAutopilotParams.put(SweepersConst.EVENT_PARAM_SN, sn);
|
||||
mStartAutopilotParams.put(SweepersConst.EVENT_PARAM_PLATE_NUM, TextUtils.isEmpty(plateNum) ? "" : plateNum);
|
||||
mStartAutopilotParams.put(SweepersConst.EVENT_PARAM_ENV_ONLINE,
|
||||
DebugConfig.getNetMode() == DebugConfig.NET_MODE_RELEASE ? true : false);
|
||||
mStartAutopilotParams.put(SweepersConst.EVENT_PARAM_TIME, dateTime);
|
||||
mStartAutopilotParams.put(SweepersConst.EVENT_PARAM_START_NAME, startName);
|
||||
mStartAutopilotParams.put(SweepersConst.EVENT_PARAM_END_NAME, endName);
|
||||
mStartAutopilotParams.put(SweepersConst.EVENT_PARAM_LINE_ID, lineId);
|
||||
|
||||
if (send) {
|
||||
// 开启成功,上报埋点
|
||||
if (startAutopilotRunnable != null &&
|
||||
UiThreadHandler.getsUiHandler().hasCallbacks(startAutopilotRunnable)) {
|
||||
UiThreadHandler.removeCallbacks(startAutopilotRunnable);
|
||||
}
|
||||
mStartAutopilotParams.put(SweepersConst.EVENT_PARAM_START_RESULT, true);
|
||||
AnalyticsManager.INSTANCE.track(mStartAutopilotKey, mStartAutopilotParams);
|
||||
} else {
|
||||
UiThreadHandler.postDelayed(startAutopilotRunnable, SweepersConst.LOOP_PERIOD_15S);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
package com.mogo.och.sweepers.util;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.mogo.eagle.core.data.autopilot.AutopilotControlParameters;
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotManager;
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
|
||||
import com.mogo.eagle.core.utilcode.util.GsonUtils;
|
||||
import com.mogo.eagle.core.utilcode.util.ToastUtils;
|
||||
import com.mogo.och.sweepers.bean.SweepersRoutesResult;
|
||||
import com.mogo.och.sweepers.constant.SweepersConst;
|
||||
import com.mogo.och.sweepers.model.SweepersOrderModel;
|
||||
|
||||
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 SweepersTrajectoryManager {
|
||||
private static final String TAG = SweepersTrajectoryManager.class.getSimpleName();
|
||||
|
||||
private static final class SingletonHolder {
|
||||
private static final SweepersTrajectoryManager INSTANCE = new SweepersTrajectoryManager();
|
||||
}
|
||||
|
||||
public static SweepersTrajectoryManager getInstance() {
|
||||
return SweepersTrajectoryManager.SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private AutopilotControlParameters.AutoPilotLine mAutoPilotLine = null;
|
||||
private Disposable mSendReqDisposable = null;
|
||||
|
||||
public SweepersTrajectoryManager() {
|
||||
mAutoPilotLine = new AutopilotControlParameters.AutoPilotLine(-1,
|
||||
"", "", "", "", 0, "",
|
||||
"", "", "", "", 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步Bus路线信息
|
||||
*/
|
||||
public void syncTrajectoryInfo() {
|
||||
SweepersRoutesResult routesResult = SweepersOrderModel.getInstance().getBusRoutesResult();
|
||||
if (SweepersOrderModel.getInstance().isWorking() && routesResult != null
|
||||
&& SweepersOrderModel.getInstance().getCurrentStationIndex() == 0
|
||||
&& !SweepersOrderModel.getInstance().isGoingToNextStation()) {
|
||||
CallerLogger.INSTANCE.d(M_BUS + TAG, "syncTrajectoryInfo() start.");
|
||||
startTrajReqLoop();
|
||||
} else {
|
||||
// 无路线信息or当前未在始发站
|
||||
CallerLogger.INSTANCE.d(M_BUS + TAG, "syncTrajectoryInfo() stop.");
|
||||
stopTrajReqLoop();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 接口MEC反馈的常规信息(MAP v2.5.0新增轨迹相关信息)
|
||||
* @param guardianInfo
|
||||
*/
|
||||
public void onAutopilotGuardian(@Nullable MogoReportMsg.MogoReportMessage guardianInfo) {
|
||||
if (guardianInfo == null || !guardianInfo.hasCode()) return;
|
||||
if ("ISYS_INIT_TRAJECTORY_START".equals(guardianInfo.getCode())) {
|
||||
// 1. 轨迹管理_轨迹开始下载(本地已有对应轨迹也触发)
|
||||
CallerLogger.INSTANCE.d(M_BUS + TAG, "onAutopilotGuardian() 轨迹开始下载");
|
||||
// ToastUtils.showShort("轨迹开始下载");
|
||||
stopTrajReqLoop();
|
||||
} else if ("ISYS_INIT_TRAJECTORY_SUCCESS".equals(guardianInfo.getCode())) {
|
||||
// 2. 轨迹管理_轨迹下载成功(本地已有对应轨迹也触发)
|
||||
CallerLogger.INSTANCE.d(M_BUS + TAG, "onAutopilotGuardian() 轨迹下载成功");
|
||||
// ToastUtils.showShort("轨迹下载成功");
|
||||
stopTrajReqLoop();
|
||||
} else if ("ISYS_INIT_TRAJECTORY_FAILURE".equals(guardianInfo.getCode())) {
|
||||
// 3. 轨迹管理_轨迹下载失败,本地无对应轨迹
|
||||
CallerLogger.INSTANCE.d(M_BUS + TAG, "onAutopilotGuardian() " +
|
||||
"轨迹下载失败,本地无对应轨迹");
|
||||
// ToastUtils.showShort("轨迹下载失败,本地无对应轨迹");
|
||||
} else if ("ISYS_INIT_TRAJECTORY_WARNING".equals(guardianInfo.getCode())) {
|
||||
// 4. 轨迹管理_轨迹下载失败,本地有对应轨迹,认为成功
|
||||
CallerLogger.INSTANCE.d(M_BUS + TAG, "onAutopilotGuardian() " +
|
||||
"轨迹下载失败,本地有对应轨迹,认为成功");
|
||||
// ToastUtils.showShort("轨迹下载失败,本地有对应轨迹,认为成功");
|
||||
} else if ("ISYS_INIT_TRAJECTORY_TIMEOUT".equals(guardianInfo.getCode())) {
|
||||
// 5. 轨迹管理_轨迹下载超时
|
||||
CallerLogger.INSTANCE.d(M_BUS + TAG, "onAutopilotGuardian() 轨迹下载超时");
|
||||
// ToastUtils.showShort("轨迹下载超时");
|
||||
}
|
||||
}
|
||||
|
||||
private void setupAutoPilotLine() {
|
||||
SweepersRoutesResult routesResult = SweepersOrderModel.getInstance().getBusRoutesResult();
|
||||
if (routesResult == null) {
|
||||
CallerLogger.INSTANCE.e(M_BUS + TAG,
|
||||
"setupAutoPilotLine(): routesResult is null.");
|
||||
return;
|
||||
} else {
|
||||
if (mAutoPilotLine == null) {
|
||||
mAutoPilotLine = new AutopilotControlParameters.AutoPilotLine(routesResult.getLineId(),
|
||||
routesResult.csvFileUrl, routesResult.csvFileMd5,
|
||||
routesResult.txtFileUrl, routesResult.txtFileMd5,
|
||||
routesResult.contrailSaveTime, routesResult.carModel,
|
||||
routesResult.csvFileUrlDPQP, routesResult.csvFileMd5DPQP,
|
||||
routesResult.txtFileUrlDPQP, routesResult.txtFileMd5DPQP,
|
||||
routesResult.contrailSaveTimeDPQP);
|
||||
} else {
|
||||
mAutoPilotLine.setLineId(routesResult.getLineId());
|
||||
mAutoPilotLine.setTrajUrl(routesResult.csvFileUrl);
|
||||
mAutoPilotLine.setTrajMd5(routesResult.csvFileMd5);
|
||||
mAutoPilotLine.setStopUrl(routesResult.txtFileUrl);
|
||||
mAutoPilotLine.setStopMd5(routesResult.txtFileMd5);
|
||||
mAutoPilotLine.setTimestamp(routesResult.contrailSaveTime);
|
||||
mAutoPilotLine.setVehicleModel(routesResult.carModel);
|
||||
mAutoPilotLine.setTrajUrl_dpqp(routesResult.csvFileUrlDPQP);
|
||||
mAutoPilotLine.setTrajMd5_dpqp(routesResult.csvFileMd5DPQP);
|
||||
mAutoPilotLine.setStopUrl_dpqp(routesResult.txtFileUrlDPQP);
|
||||
mAutoPilotLine.setStopMd5_dpqp(routesResult.txtFileMd5DPQP);
|
||||
mAutoPilotLine.setTimestamp_dpqp(routesResult.contrailSaveTimeDPQP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void clearAutoPilotLine() {
|
||||
if (mAutoPilotLine == null) return;
|
||||
mAutoPilotLine.setLineId(-1);
|
||||
mAutoPilotLine.setTrajUrl("");
|
||||
mAutoPilotLine.setTrajMd5("");
|
||||
mAutoPilotLine.setStopUrl("");
|
||||
mAutoPilotLine.setStopMd5("");
|
||||
mAutoPilotLine.setTimestamp(0);
|
||||
mAutoPilotLine.setVehicleModel("");
|
||||
mAutoPilotLine.setTrajUrl_dpqp("");
|
||||
mAutoPilotLine.setTrajMd5_dpqp("");
|
||||
mAutoPilotLine.setStopUrl_dpqp("");
|
||||
mAutoPilotLine.setStopMd5_dpqp("");
|
||||
mAutoPilotLine.setTimestamp_dpqp(0);
|
||||
}
|
||||
|
||||
private void startTrajReqLoop() {
|
||||
if (mSendReqDisposable != null && !mSendReqDisposable.isDisposed()) {
|
||||
return;
|
||||
}
|
||||
CallerLogger.INSTANCE.d(M_BUS + TAG, "startTrajReqLoop()");
|
||||
setupAutoPilotLine();
|
||||
mSendReqDisposable = Observable.interval(SweepersConst.LOOP_DELAY,
|
||||
SweepersConst.LOOP_PERIOD_10S, TimeUnit.MILLISECONDS)
|
||||
.map((aLong -> aLong + 1))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(aLong -> {
|
||||
if (aLong > SweepersConst.LOOP_SEND_TRAJ_TIMES) {
|
||||
stopTrajReqLoop();
|
||||
return;
|
||||
}
|
||||
CallerLogger.INSTANCE.d(M_BUS + TAG, "loop sendTrajectoryReq: " + aLong);
|
||||
sendTrajectoryReq();
|
||||
});
|
||||
}
|
||||
|
||||
public void stopTrajReqLoop() {
|
||||
if (mSendReqDisposable != null) {
|
||||
CallerLogger.INSTANCE.d(M_BUS + TAG, "stopTrajReqLoop()");
|
||||
mSendReqDisposable.dispose();
|
||||
mSendReqDisposable = null;
|
||||
clearAutoPilotLine();
|
||||
}
|
||||
}
|
||||
|
||||
private void sendTrajectoryReq() {
|
||||
if (mAutoPilotLine == null) {
|
||||
CallerLogger.INSTANCE.e(M_BUS + TAG, "sendTrajectoryReq(): mAutoPilotLine is null!!!");
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: 2022/6/24
|
||||
// test1
|
||||
// mAutoPilotLine.setLineId(148);
|
||||
// mAutoPilotLine.setTrajUrl("http://file-qa.zhidaozhixing.com/fileServer/upload/downloadFileStream?key=fileServer/online_car_hailing/e27c20c2da32481021d934c3ef084536/traj_148.csv");
|
||||
// mAutoPilotLine.setTrajMd5("e27c20c2da32481021d934c3ef084536");
|
||||
// mAutoPilotLine.setStopUrl("http://file-qa.zhidaozhixing.com/fileServer/upload/downloadFileStream?key=fileServer/online_car_hailing/6224c9dd2c0e2bd990c6482c0464de45/stop_148.txt");
|
||||
// mAutoPilotLine.setStopMd5("6224c9dd2c0e2bd990c6482c0464de45");
|
||||
// mAutoPilotLine.setTimestamp(1654596000000L); //20220607 18:00
|
||||
// mAutoPilotLine.setVehicleModel("红旗H9");
|
||||
|
||||
// test2
|
||||
// mAutoPilotLine.setLineId(148);
|
||||
// mAutoPilotLine.setTrajUrl("http://file-qa.zhidaozhixing.com/fileServer/upload/downloadFileStream?key=fileServer/online_car_hailing/8654497cf918be461a59c7ad8e22920d/traj_148.csv");
|
||||
// mAutoPilotLine.setTrajMd5("8654497cf918be461a59c7ad8e22920d");
|
||||
// mAutoPilotLine.setStopUrl("http://file-qa.zhidaozhixing.com/fileServer/upload/downloadFileStream?key=fileServer/online_car_hailing/1bb098b244922649bf3e7bada0d3950f/stop_148.txt");
|
||||
// mAutoPilotLine.setStopMd5("1bb098b244922649bf3e7bada0d3950f");
|
||||
// mAutoPilotLine.setTimestamp(1654761600000L); //20220609 16:00
|
||||
// mAutoPilotLine.setVehicleModel("红旗H9");
|
||||
|
||||
CallerAutoPilotManager.INSTANCE.sendTrajectoryDownloadReq(mAutoPilotLine);
|
||||
CallerLogger.INSTANCE.d(M_BUS + TAG, "sendTrajectoryReq(): "
|
||||
+ GsonUtils.toJson(mAutoPilotLine));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
package com.mogo.och.sweepers.view;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Typeface;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.mogo.och.sweepers.R;
|
||||
|
||||
/**
|
||||
* created by wujifei on 2021/3/24 16:20
|
||||
* describe:
|
||||
*/
|
||||
public class BusArcView extends View {
|
||||
|
||||
//中心的文字描述
|
||||
private String mDes = "KM/H";
|
||||
//根据数据显示的圆弧Paint
|
||||
private Paint mArcPaint;
|
||||
//圆弧颜色
|
||||
private int mArcColor;
|
||||
//圆弧的画笔的宽度
|
||||
private float mStrokeWith = getResources().getDimension(R.dimen.sweepers_ext_arcView_stroke_with);
|
||||
//文字描述的paint
|
||||
private Paint mTextPaint;
|
||||
|
||||
//当前进度夹角大小
|
||||
private float mIncludedAngle = 0;
|
||||
//当前数据
|
||||
private int currentValue;
|
||||
//最大数据
|
||||
private int maxValue = 240;
|
||||
//圆弧背景的开始和结束间的夹角大小
|
||||
private float mAngle = 270;
|
||||
//上次绘制圆弧夹角
|
||||
private float lastAngle = 0;
|
||||
|
||||
public BusArcView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public BusArcView(Context context, @Nullable AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public BusArcView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
//初始化paint
|
||||
initPaint();
|
||||
//绘制弧度
|
||||
drawArc(canvas);
|
||||
//绘制文本
|
||||
drawText(canvas);
|
||||
}
|
||||
|
||||
private void drawText(Canvas canvas) {
|
||||
Rect mRect = new Rect();
|
||||
String mValue = String.valueOf(currentValue);
|
||||
mTextPaint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
|
||||
//绘制中心的数值
|
||||
mTextPaint.getTextBounds(mValue, 0, mValue.length(), mRect);
|
||||
canvas.drawText(mValue, getWidth() / 2, getHeight() / 2 + mRect.height() / 2 - 10, mTextPaint);
|
||||
|
||||
mTextPaint.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));
|
||||
//绘制中心文字描述
|
||||
mTextPaint.setTextSize(getResources().getDimension(R.dimen.sweepers_ext_arcView_des_text_size));
|
||||
mTextPaint.getTextBounds(mDes, 0, mDes.length(), mRect);
|
||||
canvas.drawText(mDes, getWidth() / 2, getHeight() * 17 / 20 + mRect.height() / 2, mTextPaint);
|
||||
}
|
||||
|
||||
private void drawArc(Canvas canvas) {
|
||||
//绘制圆弧背景
|
||||
RectF mRectF = new RectF(mStrokeWith, mStrokeWith, getWidth() - mStrokeWith, getHeight() - mStrokeWith);
|
||||
canvas.drawArc(mRectF, 135, mAngle, false, mArcPaint);
|
||||
|
||||
//绘制当前数值对应的圆弧
|
||||
mArcPaint.setColor(mArcColor);
|
||||
//根据当前数据绘制对应的圆弧
|
||||
canvas.drawArc(mRectF, 135, mIncludedAngle, false, mArcPaint);
|
||||
}
|
||||
|
||||
private void initPaint() {
|
||||
//圆弧的paint
|
||||
mArcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
//抗锯齿
|
||||
mArcPaint.setAntiAlias(true);
|
||||
mArcPaint.setColor(Color.parseColor("#151D4C"));
|
||||
//设置透明度(数值为0-255)
|
||||
mArcPaint.setAlpha(100);
|
||||
//设置画笔的画出的形状
|
||||
mArcPaint.setStrokeJoin(Paint.Join.ROUND);
|
||||
mArcPaint.setStrokeCap(Paint.Cap.ROUND);
|
||||
//设置画笔类型
|
||||
mArcPaint.setStyle(Paint.Style.STROKE);
|
||||
//画笔宽度
|
||||
mArcPaint.setStrokeWidth(mStrokeWith);
|
||||
|
||||
//中心文字的paint
|
||||
mTextPaint = new Paint();
|
||||
mTextPaint.setAntiAlias(true);
|
||||
mTextPaint.setColor(Color.parseColor("#FFFFFF"));
|
||||
//设置文本的对齐方式
|
||||
mTextPaint.setTextAlign(Paint.Align.CENTER);
|
||||
//mTextPaint.setTextSize(getResources().getDimensionPixelSize(R.dimen.dp_12));
|
||||
mTextPaint.setTextSize(getResources().getDimension(R.dimen.sweepers_ext_arcView_center_text_size));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 为绘制弧度及数据设置动画
|
||||
*
|
||||
* @param startAngle 开始的弧度
|
||||
* @param currentAngle 需要绘制的弧度
|
||||
* @param time 动画执行的时长
|
||||
*/
|
||||
private void setAnimation(float startAngle, float currentAngle, int time) {
|
||||
//绘制当前数据对应的圆弧的动画效果
|
||||
ValueAnimator progressAnimator = ValueAnimator.ofFloat(startAngle, currentAngle);
|
||||
progressAnimator.setDuration(time);
|
||||
progressAnimator.setTarget(mIncludedAngle);
|
||||
progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
mIncludedAngle = (float) animation.getAnimatedValue();
|
||||
//重新绘制,不然不会出现效果
|
||||
postInvalidate();
|
||||
}
|
||||
});
|
||||
//开始执行动画
|
||||
progressAnimator.start();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置弧形颜色
|
||||
*
|
||||
* @param value 颜色值
|
||||
*/
|
||||
public void setArcColor(int value) {
|
||||
mArcColor = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置数据
|
||||
*
|
||||
* @param value 当前绘制的值
|
||||
*/
|
||||
public void setValues(int value) {
|
||||
//完全覆盖
|
||||
if (value > maxValue) {
|
||||
value = maxValue;
|
||||
}
|
||||
if (value < 0) {
|
||||
value = 0;
|
||||
}
|
||||
currentValue = value;
|
||||
//计算弧度比重
|
||||
float scale = (float) currentValue / maxValue;
|
||||
//计算弧度
|
||||
float currentAngle = scale * mAngle;
|
||||
//开始执行动画
|
||||
setAnimation(lastAngle, currentAngle, 1000);
|
||||
lastAngle = currentAngle;
|
||||
//重新绘制
|
||||
postInvalidate();
|
||||
}
|
||||
|
||||
|
||||
private float dp2px(float dp) {
|
||||
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
|
||||
return dp * metrics.density;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.mogo.och.sweepers.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
|
||||
import com.mogo.commons.debug.DebugConfig;
|
||||
|
||||
/**
|
||||
* 强制拦截所有touch时间的约束布局
|
||||
*
|
||||
* @author tongchenfei
|
||||
*/
|
||||
public class NoTouchConstraintLayout extends ConstraintLayout {
|
||||
public NoTouchConstraintLayout(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public NoTouchConstraintLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public NoTouchConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
if(DebugConfig.isDebug()){
|
||||
return super.onInterceptTouchEvent(ev);
|
||||
}else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
package com.mogo.och.sweepers.view;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.LinearGradient;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Shader;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.mogo.och.sweepers.R;
|
||||
|
||||
/**
|
||||
* 滑块滑动面板
|
||||
*
|
||||
* @author tongchenfei
|
||||
*/
|
||||
public class SlidePanelView extends View {
|
||||
private static final String TAG = "SlidePanelView";
|
||||
|
||||
public SlidePanelView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public SlidePanelView(Context context, @Nullable AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public SlidePanelView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.SlidePanelView);
|
||||
textSize = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_textSize, textSize);
|
||||
BLOCK_START_X = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_BLOCK_START_X, BLOCK_START_X);
|
||||
BLOCK_START_Y = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_BLOCK_START_Y, BLOCK_START_Y);
|
||||
NORMAL_TEXT_MARGIN_LEFT = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_NORMAL_TEXT_MARGIN_LEFT, NORMAL_TEXT_MARGIN_LEFT);
|
||||
NORMAL_TEXT_MARGIN_RIGHT = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_NORMAL_TEXT_MARGIN_RIGHT, NORMAL_TEXT_MARGIN_RIGHT);
|
||||
SHORT_TEXT_MARGIN_LEFT = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_SHORT_TEXT_MARGIN_LEFT, SHORT_TEXT_MARGIN_LEFT);
|
||||
SHORT_TEXT_MARGIN_RIGHT = (int) mTypedArray.getDimension(R.styleable.SlidePanelView_SHORT_TEXT_MARGIN_RIGHT, SHORT_TEXT_MARGIN_RIGHT);
|
||||
init();
|
||||
}
|
||||
|
||||
private final Paint bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
private final Paint blockPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
private final Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
|
||||
private static int textSize = 40;
|
||||
private static int BLOCK_START_X = 15;
|
||||
private static int BLOCK_START_Y = 15;
|
||||
private static int NORMAL_TEXT_MARGIN_LEFT = 40;
|
||||
private static int NORMAL_TEXT_MARGIN_RIGHT = 60;
|
||||
private static int SHORT_TEXT_MARGIN_LEFT = 60;
|
||||
private static int SHORT_TEXT_MARGIN_RIGHT = 70;
|
||||
|
||||
private int textMarginLeft = NORMAL_TEXT_MARGIN_LEFT;
|
||||
private int textMarginRight = NORMAL_TEXT_MARGIN_RIGHT;
|
||||
|
||||
private OnSlidePanelMoveToEndListener moveToEndListener;
|
||||
|
||||
private int blockWidth = 0;
|
||||
private int blockOffset = 0;
|
||||
|
||||
private float lastX;
|
||||
private boolean isToEnd = false;
|
||||
|
||||
private static final String STRING_SLIDE_TO_RIGHT = "向右滑动";
|
||||
private RectF bgRectF;
|
||||
private Bitmap bmBlock;
|
||||
|
||||
private final Matrix gradientMatrix = new Matrix();
|
||||
private float matrixTranslate;
|
||||
private final Rect textRect = new Rect();
|
||||
private LinearGradient textGradient;
|
||||
|
||||
private ObjectAnimator matrixAnim;
|
||||
|
||||
private String blockText = STRING_SLIDE_TO_RIGHT;
|
||||
private Paint.FontMetrics blockTextMetrics = new Paint.FontMetrics();
|
||||
|
||||
private static final int GRADIENT_OFFSET = 200;
|
||||
|
||||
public void setOnSlidePanelMoveToEndListener(OnSlidePanelMoveToEndListener moveToEndListener) {
|
||||
this.moveToEndListener = moveToEndListener;
|
||||
}
|
||||
|
||||
private void setBlockOffset(int blockOffset) {
|
||||
this.blockOffset = blockOffset;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
private void setMatrixTranslate(float matrixTranslate) {
|
||||
this.matrixTranslate = matrixTranslate;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.blockText = text;
|
||||
requestLayout();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
bgRectF = new RectF(0, 0, 0, 0);
|
||||
bgPaint.setColor(Color.parseColor("#CC0F1325"));
|
||||
bgPaint.setStyle(Paint.Style.FILL);
|
||||
|
||||
textPaint.setStyle(Paint.Style.FILL);
|
||||
textPaint.setTextSize(textSize);
|
||||
textPaint.setTextAlign(Paint.Align.LEFT);
|
||||
textGradient = new LinearGradient(-GRADIENT_OFFSET, 0, 0, 0, new int[]{0x33ffffff, 0xffffffff, 0x33ffffff}, null, Shader.TileMode.CLAMP);
|
||||
textGradient.setLocalMatrix(gradientMatrix);
|
||||
textPaint.setShader(textGradient);
|
||||
textPaint.getFontMetrics(blockTextMetrics);
|
||||
|
||||
bmBlock = BitmapFactory.decodeResource(getResources(), R.drawable.sweepers_base_slide_block);
|
||||
blockWidth = bmBlock.getWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
|
||||
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
|
||||
int widthSize;
|
||||
int heightSize;
|
||||
|
||||
if (blockText.length() < 5) {
|
||||
textMarginLeft = SHORT_TEXT_MARGIN_LEFT;
|
||||
textMarginRight = SHORT_TEXT_MARGIN_RIGHT;
|
||||
} else {
|
||||
textMarginLeft = NORMAL_TEXT_MARGIN_LEFT;
|
||||
textMarginRight = NORMAL_TEXT_MARGIN_RIGHT;
|
||||
}
|
||||
|
||||
if (widthMode == MeasureSpec.AT_MOST) {
|
||||
// 宽度根据图片大小,字符串长度,各种间隔确定
|
||||
// 高度根据图片大小和上下间隔确定
|
||||
textPaint.getTextBounds(blockText, 0, blockText.length(), textRect);
|
||||
widthSize = BLOCK_START_X * 2 + bmBlock.getWidth() + textMarginLeft + textMarginRight + textRect.width();
|
||||
heightSize = BLOCK_START_Y * 2 + bmBlock.getHeight();
|
||||
widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, widthMode);
|
||||
heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, heightMode);
|
||||
}
|
||||
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
}
|
||||
|
||||
private float textOffset = 0;
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
if (bgRectF != null){
|
||||
bgRectF.left = 0;
|
||||
bgRectF.top = 0;
|
||||
bgRectF.right = w;
|
||||
bgRectF.bottom = h;
|
||||
}
|
||||
|
||||
if (matrixAnim != null) {
|
||||
matrixAnim.cancel();
|
||||
}
|
||||
textOffset = (getHeight() - blockTextMetrics.ascent - blockTextMetrics.descent) / 2;
|
||||
matrixAnim = ObjectAnimator.ofFloat(this, "matrixTranslate", 0, w + GRADIENT_OFFSET).setDuration(2000);
|
||||
matrixAnim.setRepeatCount(ValueAnimator.INFINITE);
|
||||
matrixAnim.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
if (matrixAnim != null) {
|
||||
matrixAnim.start();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
if (matrixAnim != null) {
|
||||
matrixAnim.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
float x = event.getX();
|
||||
float y = event.getY();
|
||||
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
if (x > BLOCK_START_X + blockOffset && x < blockWidth + BLOCK_START_X + blockOffset && y > BLOCK_START_Y && y < getHeight() - BLOCK_START_Y) {
|
||||
isToEnd = false;
|
||||
lastX = x;
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (lastX != 0) {
|
||||
blockOffset = (int) (x - lastX);
|
||||
if (blockOffset < 0) {
|
||||
blockOffset = 0;
|
||||
}
|
||||
if (blockOffset + BLOCK_START_X + blockWidth > getWidth()) {
|
||||
// 超出右边界
|
||||
blockOffset = getWidth() - BLOCK_START_X - blockWidth;
|
||||
if (!isToEnd) {
|
||||
isToEnd = true;
|
||||
if (moveToEndListener != null) {
|
||||
moveToEndListener.moveToEnd();
|
||||
}
|
||||
startBlockBackAnim();
|
||||
}
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
// 执行滑块回归动画
|
||||
if (!isToEnd) {
|
||||
startBlockBackAnim();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void startBlockBackAnim() {
|
||||
ObjectAnimator blockBackanimator = ObjectAnimator.ofInt(this, "blockOffset", blockOffset, 0);
|
||||
blockBackanimator.setInterpolator(new DecelerateInterpolator());
|
||||
blockBackanimator.setDuration(1000 * blockOffset / getWidth());
|
||||
blockBackanimator.start();
|
||||
lastX = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
// 画背景
|
||||
canvas.drawRoundRect(bgRectF, (float) getHeight() / 2, (float) getHeight() / 2, bgPaint);
|
||||
// 画文字
|
||||
gradientMatrix.setTranslate(matrixTranslate, 0);
|
||||
textGradient.setLocalMatrix(gradientMatrix);
|
||||
canvas.save();
|
||||
canvas.drawText(blockText, blockWidth + BLOCK_START_X + textMarginLeft, textOffset, textPaint);
|
||||
canvas.restore();
|
||||
// 画滑块
|
||||
canvas.drawBitmap(bmBlock, BLOCK_START_X + blockOffset, BLOCK_START_Y, blockPaint);
|
||||
}
|
||||
|
||||
public interface OnSlidePanelMoveToEndListener {
|
||||
/**
|
||||
* 滑块滑到了末尾
|
||||
*/
|
||||
void moveToEnd();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.mogo.och.sweepers.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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/sweepers_autopilot_text_color_normal"/>
|
||||
</selector>
|
||||
BIN
OCH/mogo-och-sweepers/src/main/res/drawable-xhdpi-2560x1440/end_maker_icon.png
Executable file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
OCH/mogo-och-sweepers/src/main/res/drawable-xhdpi-2560x1440/icon_ai_normal.png
Executable file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
OCH/mogo-och-sweepers/src/main/res/drawable-xhdpi-2560x1440/icon_ai_select.png
Executable file
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
|
After Width: | Height: | Size: 100 KiB |
|
After Width: | Height: | Size: 15 KiB |
BIN
OCH/mogo-och-sweepers/src/main/res/drawable-xhdpi-2560x1440/start_failure.png
Executable file
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
BIN
OCH/mogo-och-sweepers/src/main/res/drawable-xhdpi-2560x1440/start_success.png
Executable file
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 1004 B |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
BIN
OCH/mogo-och-sweepers/src/main/res/drawable-xhdpi-2560x1600/end_maker_icon.png
Executable file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
OCH/mogo-och-sweepers/src/main/res/drawable-xhdpi-2560x1600/icon_ai_normal.png
Executable file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
OCH/mogo-och-sweepers/src/main/res/drawable-xhdpi-2560x1600/icon_ai_select.png
Executable file
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
|
After Width: | Height: | Size: 100 KiB |
|
After Width: | Height: | Size: 15 KiB |
BIN
OCH/mogo-och-sweepers/src/main/res/drawable-xhdpi-2560x1600/start_failure.png
Executable file
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
BIN
OCH/mogo-och-sweepers/src/main/res/drawable-xhdpi-2560x1600/start_success.png
Executable file
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 25 KiB |