[6.6.0]
[项目结构、扫码枪添加手机号]
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
package com.mogo.och.shuttle.passenger
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.alibaba.android.arouter.facade.annotation.Route
|
||||
import com.mogo.eagle.core.data.config.FunctionBuildConfig
|
||||
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
|
||||
import com.mogo.eagle.core.utilcode.util.ActivityUtils
|
||||
import com.mogo.eagle.core.utilcode.util.DeviceUtils
|
||||
import com.mogo.eagle.core.utilcode.util.MultiDisplayUtils
|
||||
import com.mogo.och.common.module.constant.OchCommonConst
|
||||
import com.mogo.och.common.module.biz.provider.CommonServiceImpl
|
||||
import com.mogo.och.common.module.wigets.media.MediaPlayerActivity
|
||||
import com.mogo.och.shuttle.passenger.model.TicketModel
|
||||
import com.mogo.och.shuttle.passenger.ui.BusPStatusBarView
|
||||
import com.mogo.och.shuttle.passenger.ui.BusPassengerRouteFragment
|
||||
import com.mogo.och.shuttle.passenger.ui.PM2BaseFragment
|
||||
import com.mogo.och.shuttle.passenger.ui.widget.M2StatusBarView
|
||||
|
||||
/**
|
||||
* 网约车-Bus-乘客端
|
||||
*
|
||||
* Created on 2022/3/29
|
||||
*/
|
||||
@Route(path = OchCommonConst.SHUTTLE_PASSENGER_WEAKNET)
|
||||
class ShuttlePassengerProvider : CommonServiceImpl() {
|
||||
|
||||
private val tag = ShuttlePassengerProvider::class.java.simpleName
|
||||
private var mPM2Fragment: Fragment?=null
|
||||
|
||||
override fun init(context: Context) {
|
||||
TicketModel.load()
|
||||
}
|
||||
|
||||
override fun getStatusBarView(context: Context): View {
|
||||
if(statusBarView==null){
|
||||
statusBarView = if (AppIdentityModeUtils.isB2(FunctionBuildConfig.appIdentityMode)) {
|
||||
M2StatusBarView(context);
|
||||
} else if (AppIdentityModeUtils.isB1(FunctionBuildConfig.appIdentityMode)) {
|
||||
BusPStatusBarView(context);
|
||||
}else{
|
||||
BusPStatusBarView(context);
|
||||
}
|
||||
}
|
||||
return statusBarView!!
|
||||
}
|
||||
|
||||
override fun getFragment(): Fragment {
|
||||
if (AppIdentityModeUtils.isB1(FunctionBuildConfig.appIdentityMode) && DeviceUtils.isEB5Model()) {
|
||||
MultiDisplayUtils.startActWithSecond(ActivityUtils.getTopActivity(), MediaPlayerActivity::class.java)
|
||||
}
|
||||
if(mPM2Fragment==null){
|
||||
mPM2Fragment = if (AppIdentityModeUtils.isB2(FunctionBuildConfig.appIdentityMode)) {
|
||||
PM2BaseFragment()
|
||||
}else if (AppIdentityModeUtils.isB1(FunctionBuildConfig.appIdentityMode)) {
|
||||
BusPassengerRouteFragment()
|
||||
}else{
|
||||
BusPassengerRouteFragment()
|
||||
}
|
||||
}
|
||||
return mPM2Fragment!!
|
||||
}
|
||||
|
||||
override fun resetFragment() {
|
||||
super.resetFragment()
|
||||
mPM2Fragment = null
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.mogo.och.shuttle.passenger.bean.request;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2021/3/22
|
||||
*
|
||||
* 根据车机行驶线路站点信息
|
||||
*/
|
||||
class PassengerQueryLineRequest {
|
||||
|
||||
private String sn;
|
||||
public PassengerQueryLineRequest(String sn) {
|
||||
this.sn = sn;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.mogo.och.shuttle.passenger.bean.request;
|
||||
|
||||
public
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2021/3/22
|
||||
*
|
||||
* 根据车机行驶线路站点信息
|
||||
*/
|
||||
class PassengerWriteOffRequest {
|
||||
|
||||
private String sn;
|
||||
private String orderNo;
|
||||
private String uid;
|
||||
|
||||
public PassengerWriteOffRequest(String orderNo, String uid) {
|
||||
this.orderNo = orderNo;
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
public PassengerWriteOffRequest(String sn, String orderNo, String uid) {
|
||||
this.sn = sn;
|
||||
this.orderNo = orderNo;
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
public String getSn() {
|
||||
return sn;
|
||||
}
|
||||
|
||||
public void setSn(String sn) {
|
||||
this.sn = sn;
|
||||
}
|
||||
|
||||
public String getOrderNo() {
|
||||
return orderNo;
|
||||
}
|
||||
|
||||
public void setOrderNo(String orderNo) {
|
||||
this.orderNo = orderNo;
|
||||
}
|
||||
|
||||
public String getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public void setUid(String uid) {
|
||||
this.uid = uid;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.mogo.och.shuttle.passenger.bean.response;
|
||||
|
||||
import com.mogo.eagle.core.data.BaseData;
|
||||
|
||||
/**
|
||||
* @author congtaowang
|
||||
* @since 2021/3/22
|
||||
*
|
||||
* 小巴车运营状态返回参数
|
||||
*/
|
||||
public class PassengerOperationStatusResponse extends BaseData {
|
||||
|
||||
public Result data;
|
||||
|
||||
public static class Result {
|
||||
private String sn; //司机屏sn
|
||||
private String phone; //司机手机号
|
||||
public String plateNumber; //车牌号
|
||||
public int driverStatus;//0:已收车,1:已出车
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.mogo.och.shuttle.passenger.bean.response;
|
||||
|
||||
import com.mogo.eagle.core.data.BaseData;
|
||||
import com.mogo.och.data.bean.BusRoutesResult;
|
||||
|
||||
/**
|
||||
* 网约车小巴路线接口请求响应结果 返回的是对应司机屏的线路信息
|
||||
*
|
||||
* @author tongchenfei
|
||||
*/
|
||||
public class PassengerRoutesResponse extends BaseData {
|
||||
private BusRoutesResult data;
|
||||
|
||||
public BusRoutesResult getResult() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setResult(BusRoutesResult data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "OchBusRoutesResponse{" +
|
||||
"data=" + data +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.mogo.och.shuttle.passenger.bean.response
|
||||
|
||||
import com.mogo.eagle.core.data.BaseData
|
||||
|
||||
|
||||
data class PassengerWriteOffResponse(val data: Result?) : BaseData(){
|
||||
data class Result(
|
||||
val phone: String?,
|
||||
val ticketSize: Int?,
|
||||
val ticketName: String?,
|
||||
val remainingTimes: Long?
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.mogo.och.shuttle.passenger.constant
|
||||
|
||||
/**
|
||||
* Created on 2021/12/6
|
||||
*/
|
||||
class BusPassengerConst {
|
||||
companion object {
|
||||
|
||||
// OCH arouter 路由path
|
||||
const val PATH = "/passenger/api"
|
||||
|
||||
// 轮询line
|
||||
const val LOOP_LINE_2S = 2 * 1000L
|
||||
const val LOOP_LINE_1S = 1 * 1000L
|
||||
const val LOOP_DELAY = 100L
|
||||
|
||||
// 无状态
|
||||
const val STATION_STATUS_IDLE = 0
|
||||
// 已过站(历史站)
|
||||
const val STATION_STATUS_LEAVING = 1
|
||||
// 到站(当前站)
|
||||
const val STATION_STATUS_STOPPED = 2
|
||||
// 未到站(未到站)
|
||||
const val STATION_STATUS_ARRIVING = 3
|
||||
|
||||
//bus平均速度 bus的平均里程:25km/h
|
||||
const val BUS_AVERAGE_SPEED = 10
|
||||
//接驳/B2平均速度 bus的平均里程:10km/h
|
||||
const val SHUTTLE_AVERAGE_SPEED = 10
|
||||
|
||||
const val QUERY_BUS_P_STATION_DELAY = 3 * 1000L
|
||||
|
||||
const val ARRIVE_DISTANCE_4_STATION_INTRODUCE = 200 //站点介绍
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package com.mogo.och.shuttle.passenger.model
|
||||
|
||||
import com.mogo.commons.AbsMogoApplication
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_BUS_P
|
||||
import com.mogo.eagle.core.utilcode.util.GsonUtils
|
||||
import com.mogo.eagle.core.utilcode.util.RegexUtils
|
||||
import com.mogo.och.common.module.manager.socket.lan.bean.WriteOffMsg
|
||||
import com.mogo.och.common.module.manager.socket.lan.LanSocketManager
|
||||
import com.mogo.och.common.module.network.OchCommonServiceCallback
|
||||
import com.mogo.och.shuttle.passenger.bean.request.PassengerWriteOffRequest
|
||||
import com.mogo.och.shuttle.passenger.bean.response.PassengerWriteOffResponse
|
||||
import com.mogo.och.common.module.manager.scnner.ScannerManager
|
||||
import com.mogo.och.common.module.manager.scnner.StateChangeListener
|
||||
import com.mogo.och.shuttle.passenger.network.PassengerServiceManager
|
||||
|
||||
object TicketModel : StateChangeListener {
|
||||
|
||||
private const val TAG = "TicketModel"
|
||||
|
||||
init {
|
||||
ScannerManager.addStateChangeListener(TAG, this)
|
||||
}
|
||||
|
||||
fun load(){
|
||||
|
||||
}
|
||||
|
||||
override fun parseData(params: MutableMap<String, Any>, payload: String?) {
|
||||
val orderNo = params["orderNo"]
|
||||
val uid = params["uid"]
|
||||
val phone = params["phone"]
|
||||
if(orderNo is String && uid is String){
|
||||
var phoneNum = ""
|
||||
if(phone is String){
|
||||
if (RegexUtils.isMobileExact(phone)) {
|
||||
phoneNum = phone
|
||||
}
|
||||
}
|
||||
writeOffTicket(orderNo,uid,phoneNum)
|
||||
}else{
|
||||
// 通知司机屏二维码错误
|
||||
sendMessage2Driver("参数错误:${payload}","")
|
||||
}
|
||||
}
|
||||
|
||||
private fun writeOffTicket(orderNo: String, uid: String, phoneNum: String) {
|
||||
val passengerWriteOffRequest = PassengerWriteOffRequest(orderNo, uid)
|
||||
PassengerServiceManager.writeOffTicket(AbsMogoApplication.getApp(),
|
||||
passengerWriteOffRequest,
|
||||
object : OchCommonServiceCallback<PassengerWriteOffResponse> {
|
||||
override fun onSuccess(data: PassengerWriteOffResponse?) {
|
||||
if (data?.data == null) return
|
||||
val ticketInfo =
|
||||
"核销成功:票种名称:${data.data.ticketName},车票数量:${data.data.ticketSize},预留手机号:${data.data.phone},时间:${data.data.remainingTimes}"
|
||||
CallerLogger.d(M_BUS_P + TAG, ticketInfo)
|
||||
sendMessage2DriverSuccess(data.data,orderNo)
|
||||
}
|
||||
|
||||
override fun onFail(code: Int, msg: String?) {
|
||||
CallerLogger.d(M_BUS_P + TAG, "核销失败 ${code}-----${msg}")
|
||||
|
||||
when (code) {
|
||||
6002 -> {sendMessage2Driver("同一订单核销间隔时间需大于2分钟",phoneNum)}
|
||||
1009 -> {sendMessage2Driver("车票所选乘车日期非今日",phoneNum)}
|
||||
1005 -> {sendMessage2Driver("车辆未登录、或没有任务",phoneNum)}
|
||||
1006 -> {sendMessage2Driver("车票路线信息与当前车辆执行任务的路线信息不符合",phoneNum)}
|
||||
1008 -> {sendMessage2Driver("车票剩余可用次数为0",phoneNum)}
|
||||
6001 -> {sendMessage2Driver("二维码已过期",phoneNum)}
|
||||
1012 -> {sendMessage2Driver("当前用户下单路线非当前的车辆所属公司",phoneNum)}
|
||||
else -> {
|
||||
when (msg) {
|
||||
"6002" -> {sendMessage2Driver("同一订单核销间隔时间需大于2分钟",phoneNum)}
|
||||
"1009" -> {sendMessage2Driver("车票所选乘车日期非今日",phoneNum)}
|
||||
"1005" -> {sendMessage2Driver("车辆未登录、或没有任务",phoneNum)}
|
||||
"1006" -> {sendMessage2Driver("车票路线信息与当前车辆执行任务的路线信息不符合",phoneNum)}
|
||||
"1008" -> {sendMessage2Driver("车票剩余可用次数为0",phoneNum)}
|
||||
"6001" -> {sendMessage2Driver("二维码已过期",phoneNum)}
|
||||
"1012" -> {sendMessage2Driver("当前用户下单路线非当前的车辆所属公司",phoneNum)}
|
||||
else -> {
|
||||
sendMessage2Driver(msg?:"",phoneNum)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
sendMessage2Driver("网络错误",phoneNum)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun sendMessage2Driver(message:String,phone:String){
|
||||
val msg = WriteOffMsg(false, phone, 0, "", "验票失败,${message}","")
|
||||
CallerLogger.d(M_BUS_P + TAG, "sendTaskDetailsToClients = " + GsonUtils.toJson(msg))
|
||||
LanSocketManager.sendMsgToServer(msg)
|
||||
}
|
||||
private fun sendMessage2DriverSuccess(message: PassengerWriteOffResponse.Result,orderNo: String){
|
||||
val msg = WriteOffMsg(true, message.phone, message.ticketSize, message.ticketName, "",orderNo)
|
||||
CallerLogger.d(M_BUS_P + TAG, "sendTaskDetailsToClients = " + GsonUtils.toJson(msg))
|
||||
LanSocketManager.sendMsgToServer(msg)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.mogo.och.shuttle.passenger.network
|
||||
|
||||
import android.content.Context
|
||||
import com.mogo.cloud.passport.MoGoAiCloudClientConfig
|
||||
import com.mogo.eagle.core.network.MoGoRetrofitFactory
|
||||
import com.mogo.commons.storage.SharedPrefsMgr
|
||||
import com.mogo.eagle.core.utilcode.util.StringUtils
|
||||
import com.mogo.eagle.core.utilcode.util.ToastUtils
|
||||
import com.mogo.och.common.module.biz.lansocket.LoginLanPassengerSocket
|
||||
import com.mogo.och.common.module.constant.OchCommonConst
|
||||
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
|
||||
import com.mogo.och.common.module.network.OchCommonServiceCallback
|
||||
import com.mogo.och.common.module.network.OchCommonSubscribeImpl
|
||||
import com.mogo.och.common.module.network.interceptor.transformTry
|
||||
import com.mogo.och.shuttle.passenger.bean.request.PassengerQueryLineRequest
|
||||
import com.mogo.och.shuttle.passenger.bean.request.PassengerWriteOffRequest
|
||||
import com.mogo.och.shuttle.passenger.bean.response.PassengerOperationStatusResponse
|
||||
import com.mogo.och.shuttle.passenger.bean.response.PassengerRoutesResponse
|
||||
import com.mogo.och.shuttle.passenger.bean.response.PassengerWriteOffResponse
|
||||
|
||||
/**
|
||||
* Created on 2022/3/31
|
||||
*/
|
||||
object PassengerServiceManager {
|
||||
|
||||
private var driverSnCache = ""
|
||||
|
||||
private val TAG = "PassengerServiceManager"
|
||||
|
||||
private var mShuttleBusPassengerServiceApi =
|
||||
MoGoRetrofitFactory.getInstance(OchCommonConst.getShuttleUrl()).create(
|
||||
ServiceApi::class.java)
|
||||
|
||||
/**
|
||||
* 查询绑定行驶的小巴车路线
|
||||
* @param context
|
||||
* @param callback
|
||||
*/
|
||||
@JvmStatic
|
||||
fun queryDriverSiteByCoordinate(
|
||||
context: Context, callback: OchCommonServiceCallback<PassengerRoutesResponse>?
|
||||
) {
|
||||
mShuttleBusPassengerServiceApi.queryDriverSiteByCoordinate(
|
||||
MoGoAiCloudClientConfig.getInstance().serviceAppId,
|
||||
SharedPrefsMgr.getInstance().token,
|
||||
PassengerQueryLineRequest(
|
||||
LoginLanPassengerSocket.driverSn
|
||||
)
|
||||
).transformTry()
|
||||
.subscribe(OchCommonSubscribeImpl(context, callback, "queryDriverSiteByCoordinate",false))
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询司机端出车收车状态,以及车牌号
|
||||
* @param context
|
||||
* @param callback
|
||||
*/
|
||||
@JvmStatic
|
||||
fun queryDriverOperationStatus(
|
||||
context: Context,
|
||||
callback: OchCommonServiceCallback<PassengerOperationStatusResponse>?
|
||||
) {
|
||||
mShuttleBusPassengerServiceApi.queryDriverOperationStatus(
|
||||
MoGoAiCloudClientConfig.getInstance().serviceAppId,
|
||||
SharedPrefsMgr.getInstance().token,
|
||||
LoginLanPassengerSocket.driverSn
|
||||
)
|
||||
.transformTry()
|
||||
.subscribe(OchCommonSubscribeImpl(context, callback, "queryDriverOperationStatus"))
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询司机端出车收车状态,以及车牌号
|
||||
* @param context
|
||||
* @param callback
|
||||
*/
|
||||
@JvmStatic
|
||||
fun writeOffTicket(
|
||||
context: Context,
|
||||
ticketInfo: PassengerWriteOffRequest,
|
||||
callback: OchCommonServiceCallback<PassengerWriteOffResponse>?,
|
||||
) {
|
||||
ticketInfo.sn = LoginLanPassengerSocket.driverSn
|
||||
if(StringUtils.isEmpty(LoginLanPassengerSocket.driverSn)){
|
||||
ToastUtils.showShort("请链接司机屏${ticketInfo.uid}")
|
||||
OchChainLogManager.writeChainLogScanner(TAG +"onError","无司机屏sn请处理")
|
||||
return
|
||||
}
|
||||
mShuttleBusPassengerServiceApi.writeOffTicket(
|
||||
MoGoAiCloudClientConfig.getInstance().serviceAppId,
|
||||
SharedPrefsMgr.getInstance().token,
|
||||
ticketInfo
|
||||
)
|
||||
.transformTry()
|
||||
.subscribe(OchCommonSubscribeImpl(context, callback, "writeOff"))
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.mogo.och.shuttle.passenger.network;
|
||||
|
||||
import com.mogo.och.shuttle.passenger.bean.request.PassengerQueryLineRequest;
|
||||
import com.mogo.och.shuttle.passenger.bean.request.PassengerWriteOffRequest;
|
||||
import com.mogo.och.shuttle.passenger.bean.response.PassengerOperationStatusResponse;
|
||||
import com.mogo.och.shuttle.passenger.bean.response.PassengerRoutesResponse;
|
||||
import com.mogo.och.shuttle.passenger.bean.response.PassengerWriteOffResponse;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import retrofit2.http.Body;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.Header;
|
||||
import retrofit2.http.Headers;
|
||||
import retrofit2.http.POST;
|
||||
import retrofit2.http.Query;
|
||||
|
||||
/**
|
||||
* Created on 2022/3/31
|
||||
*
|
||||
* Bus乘客端接口定义
|
||||
*/
|
||||
public interface ServiceApi {
|
||||
/**
|
||||
* 查询bus司机端绑定路线
|
||||
* @return 接口返回数据
|
||||
*/
|
||||
@Headers( {"Content-Type:application/json;charset=UTF-8"} )
|
||||
@POST( "/och-shuttle-cabin/api/business/v1/passenger/lineDataWithDriver/query" )
|
||||
Observable<PassengerRoutesResponse> queryDriverSiteByCoordinate(@Header("appId") String appId, @Header("ticket") String ticket, @Body PassengerQueryLineRequest request);
|
||||
|
||||
/**
|
||||
* 查询司机端的登陆状态
|
||||
* @param sn
|
||||
* @return
|
||||
*/
|
||||
@Headers({"Content-type:application/json;charset=UTF-8"})
|
||||
// @GET("/autopilot-car-hailing/car/v2/driver/bus/passenger/takeOrderStatus/query")
|
||||
@GET("/och-shuttle-cabin/api/business/v1/passenger/loginStatus")
|
||||
Observable<PassengerOperationStatusResponse> queryDriverOperationStatus(@Header ("appId") String appId, @Header("ticket") String ticket, @Query("sn") String sn);
|
||||
|
||||
/**
|
||||
* 核销接口
|
||||
*/
|
||||
@Headers({"Content-type:application/json;charset=UTF-8"})
|
||||
@POST("/och-vehicle/api/scanner/device/writeOff")
|
||||
Observable<PassengerWriteOffResponse> writeOffTicket(@Header ("appId") String appId, @Header("ticket") String ticket, @Body PassengerWriteOffRequest request);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.mogo.och.shuttle.passenger.callback;
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2021/10/22
|
||||
*/
|
||||
public interface IBusPassegerDriverStatusCallback {
|
||||
void changeOperationStatus(boolean changeStatus);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.mogo.och.shuttle.passenger.callback;
|
||||
|
||||
/**
|
||||
* Created on 2022/3/31
|
||||
*
|
||||
* Model->Presenter回调:ADAS相关(自动驾驶状态回调,到达终点等等)
|
||||
*/
|
||||
public interface IBusPassengerADASStatusCallback {
|
||||
|
||||
// 自动驾驶可用状态
|
||||
void onAutopilotEnable();
|
||||
|
||||
// 自动驾驶不可用状态
|
||||
void onAutopilotDisable();
|
||||
|
||||
// 自动驾驶运行中
|
||||
void onAutopilotRunning();
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.mogo.och.shuttle.passenger.callback;
|
||||
|
||||
/**
|
||||
* Created on 2022/3/31
|
||||
*/
|
||||
public interface IBusPassengerAutopilotPlanningCallback {
|
||||
void routePlanningToNextStationChanged(long meters, long timeInSecond);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.mogo.och.shuttle.passenger.callback;
|
||||
|
||||
import com.mogo.eagle.core.data.map.MogoLocation;
|
||||
|
||||
/**
|
||||
* Created on 2022/3/31
|
||||
*
|
||||
* Model->Presenter回调:状态控制器监听(accOn、adas ui show、voice ui show、push ui show、v2x ui show等等)
|
||||
*/
|
||||
public interface IBusPassengerControllerStatusCallback {
|
||||
// 自车定位
|
||||
void onCarLocationChanged(MogoLocation location);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.mogo.och.shuttle.passenger.callback;
|
||||
|
||||
import com.mogo.och.data.bean.BusStationBean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2022/4/6
|
||||
*/
|
||||
public interface IBusPassengerRouteLineInfoCallback {
|
||||
void updateLineInfo(String lineName);
|
||||
void updateStationsInfo(List<BusStationBean> stations, int currentStationIndex, boolean isArrived);
|
||||
void showNoTaskView();
|
||||
void hideNoTaskView();
|
||||
}
|
||||
@@ -0,0 +1,496 @@
|
||||
package com.mogo.och.shuttle.passenger.model;
|
||||
|
||||
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS_P;
|
||||
import static com.mogo.och.shuttle.passenger.constant.BusPassengerConst.QUERY_BUS_P_STATION_DELAY;
|
||||
import static com.mogo.och.shuttle.passenger.constant.BusPassengerConst.STATION_STATUS_STOPPED;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
|
||||
import com.mogo.aicloud.services.socket.MogoAiCloudSocketManager;
|
||||
import com.mogo.commons.module.intent.IMogoIntentListener;
|
||||
import com.mogo.commons.module.intent.IntentManager;
|
||||
import com.mogo.eagle.core.function.api.telematic.IReceivedMsgListener;
|
||||
import com.mogo.eagle.core.function.call.telematic.CallerTelematicListenerManager;
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.Logger;
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant;
|
||||
import com.mogo.eagle.core.utilcode.util.GsonUtils;
|
||||
import com.mogo.eagle.core.utilcode.util.StringUtils;
|
||||
import com.mogo.eagle.core.utilcode.util.ToastUtils;
|
||||
import com.mogo.och.common.module.biz.lansocket.LoginLanPassengerSocket;
|
||||
import com.mogo.och.common.module.manager.autopilot.autopilot.IOchAutopilotStatusListener;
|
||||
import com.mogo.och.common.module.manager.autopilot.autopilot.OchAutoPilotStatusListenerManager;
|
||||
import com.mogo.och.common.module.manager.autopilot.location.OchLocationManager;
|
||||
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager;
|
||||
import com.mogo.och.common.module.manager.socket.lan.LanSocketManager;
|
||||
import com.mogo.och.common.module.manager.socket.lan.bean.BusinessType;
|
||||
import com.mogo.och.common.module.voice.VoiceNotice;
|
||||
import com.mogo.och.shuttle.passenger.R;
|
||||
import com.mogo.och.common.module.manager.socket.lan.bean.AppConnectMsg;
|
||||
import com.mogo.och.common.module.manager.socket.lan.bean.BaseDPMsg;
|
||||
import com.mogo.och.common.module.manager.socket.lan.bean.DPMsgType;
|
||||
import com.mogo.och.common.module.manager.socket.lan.bean.TaskDetailsMsg;
|
||||
import com.mogo.och.common.module.manager.socket.cloud.OCHSocketMessageManager;
|
||||
import com.mogo.och.common.module.constant.OchCommonConst;
|
||||
import com.mogo.och.common.module.manager.distance.IDistanceListener;
|
||||
import com.mogo.och.common.module.manager.distance.TrajectoryAndDistanceManager;
|
||||
import com.mogo.och.common.module.utils.DateTimeUtil;
|
||||
import com.mogo.eagle.core.data.config.FunctionBuildConfig;
|
||||
import com.mogo.eagle.core.data.map.MogoLocation;
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener;
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener;
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
|
||||
import com.mogo.eagle.core.utilcode.util.NetworkUtils;
|
||||
import com.mogo.och.shuttle.passenger.bean.response.PassengerOperationStatusResponse;
|
||||
import com.mogo.och.shuttle.passenger.bean.response.PassengerRoutesResponse;
|
||||
import com.mogo.och.shuttle.passenger.callback.IBusPassegerDriverStatusCallback;
|
||||
import com.mogo.och.shuttle.passenger.callback.IBusPassengerADASStatusCallback;
|
||||
import com.mogo.och.shuttle.passenger.callback.IBusPassengerAutopilotPlanningCallback;
|
||||
import com.mogo.och.shuttle.passenger.callback.IBusPassengerControllerStatusCallback;
|
||||
import com.mogo.och.shuttle.passenger.callback.IBusPassengerRouteLineInfoCallback;
|
||||
import com.mogo.och.shuttle.passenger.constant.BusPassengerConst;
|
||||
import com.mogo.och.shuttle.passenger.network.BusPassengerModelLoopManager;
|
||||
import com.mogo.och.common.module.network.OchCommonServiceCallback;
|
||||
import com.mogo.och.common.module.manager.socket.cloud.AbnormalFactorsLoopManager;
|
||||
import com.mogo.och.data.bean.BusRoutesResult;
|
||||
import com.mogo.och.data.bean.BusStationBean;
|
||||
import com.mogo.och.data.bean.BusTransferData;
|
||||
import com.mogo.och.shuttle.passenger.network.PassengerServiceManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Created on 2022/3/31
|
||||
*/
|
||||
public class BusPassengerModel {
|
||||
private static final String TAG = BusPassengerModel.class.getSimpleName();
|
||||
private static final class SingletonHolder {
|
||||
private static final BusPassengerModel INSTANCE = new BusPassengerModel();
|
||||
}
|
||||
|
||||
public static BusPassengerModel getInstance() {
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private Context mContext;
|
||||
private IBusPassengerADASStatusCallback mADASStatusCallback; //Model->Presenter:自动驾驶状态相关
|
||||
private IBusPassengerAutopilotPlanningCallback mAutopilotPlanningCallback; //Model->Presenter:自动驾驶线路规划
|
||||
private Map<String, IBusPassengerControllerStatusCallback> mControllerStatusCallbackMap = new ConcurrentHashMap<>();
|
||||
|
||||
private IBusPassegerDriverStatusCallback mDriverStatusCallback; //出车收车状态
|
||||
private IBusPassengerRouteLineInfoCallback mRouteLineInfoCallback; // bus路线信息更新
|
||||
|
||||
private BusRoutesResult routesResult = null;
|
||||
|
||||
List<BusStationBean> mStations = new ArrayList<>();
|
||||
private int mNextStationIndex = 0;// 要到达站的index
|
||||
|
||||
private volatile boolean isGoingToNextStation = false;
|
||||
|
||||
private static final int MSG_QUERY_BUS_P_STATION = 1001;
|
||||
private final Handler handler = new Handler(new Handler.Callback() {
|
||||
@Override
|
||||
public boolean handleMessage(Message msg) {
|
||||
if ( msg.what == MSG_QUERY_BUS_P_STATION ) {
|
||||
queryDriverOperationStatus();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
private BusPassengerModel() {
|
||||
}
|
||||
|
||||
public void init( Context context ) {
|
||||
mContext = context.getApplicationContext();
|
||||
initListeners();
|
||||
queryDriverOperationStatus();
|
||||
queryDriverByLocalDriver();
|
||||
startOrStopOrderLoop(true);
|
||||
}
|
||||
|
||||
private void queryDriverByLocalDriver() {
|
||||
//本地去请求司机端
|
||||
TaskDetailsMsg msg = new TaskDetailsMsg("task", BusinessType.shuttle);
|
||||
|
||||
LanSocketManager.sendMsgToServer(msg);
|
||||
}
|
||||
|
||||
public void setDriverStatusCallback(IBusPassegerDriverStatusCallback callback){
|
||||
this.mDriverStatusCallback = callback;
|
||||
}
|
||||
|
||||
public void setRouteLineInfoCallback(IBusPassengerRouteLineInfoCallback callback){
|
||||
this.mRouteLineInfoCallback = callback;
|
||||
}
|
||||
|
||||
private void queryDriverOperationDelay() {
|
||||
handler.sendEmptyMessageDelayed( MSG_QUERY_BUS_P_STATION, QUERY_BUS_P_STATION_DELAY );
|
||||
}
|
||||
|
||||
private void queryDriverOperationStatus() {
|
||||
PassengerServiceManager.queryDriverOperationStatus(mContext
|
||||
, new OchCommonServiceCallback<PassengerOperationStatusResponse>() {
|
||||
@Override
|
||||
public void onSuccess(PassengerOperationStatusResponse data) {
|
||||
if (data == null || data.data == null) return;
|
||||
if (mDriverStatusCallback != null) {
|
||||
CallerLogger.d( M_BUS_P + TAG, "queryDriverOperationStatus = %s", data.data.plateNumber );
|
||||
mDriverStatusCallback.changeOperationStatus(data.data.driverStatus == 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError() {
|
||||
if (!NetworkUtils.isConnected(mContext)) {
|
||||
ToastUtils.showShort(mContext.getString(R.string.network_error_tip));
|
||||
} else {
|
||||
ToastUtils.showShort(mContext.getString(R.string.request_error_tip));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail(int code, String msg) {
|
||||
//延迟3s再次查询
|
||||
queryDriverOperationDelay();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void queryDriverSiteByCoordinate(){
|
||||
PassengerServiceManager.queryDriverSiteByCoordinate(mContext
|
||||
, new OchCommonServiceCallback<PassengerRoutesResponse>() {
|
||||
@Override
|
||||
public void onSuccess(PassengerRoutesResponse data) {
|
||||
if ( data == null || data.getResult() == null) {
|
||||
CallerLogger.d( M_BUS_P + TAG, "queryDriverSiteByCoordinate = null");
|
||||
clearLocalRouteResult();
|
||||
return;
|
||||
}
|
||||
if (routesResult != null && data.getResult().equals(routesResult)){
|
||||
CallerLogger.d( M_BUS_P + TAG, "queryDriverSiteByCoordinate = not update");
|
||||
return;
|
||||
}
|
||||
|
||||
OchChainLogManager.writeChainLog("线路发生变化",data.toString());
|
||||
|
||||
if (routesResult != null &&
|
||||
routesResult.getWriteVersion() < data.getResult().getWriteVersion()){
|
||||
routesResult = data.getResult();
|
||||
}
|
||||
|
||||
if (routesResult == null){
|
||||
routesResult = data.getResult();
|
||||
}
|
||||
|
||||
updatePassengerRouteInfo(routesResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError() {
|
||||
CallerLogger.d( M_BUS_P + TAG, "queryDriverSiteByCoordinate = onError ="
|
||||
+ ", sn = " + LoginLanPassengerSocket.INSTANCE.getDriverSn());
|
||||
queryDriverByLocalDriver();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail(int code, String msg) {
|
||||
CallerLogger.d( M_BUS_P + TAG, "queryDriverSiteByCoordinate = %s", msg
|
||||
+ ", sn = " +LoginLanPassengerSocket.INSTANCE.getDriverSn());
|
||||
if (code == 1003){
|
||||
queryDriverOperationDelay();
|
||||
}
|
||||
if (LoginLanPassengerSocket.INSTANCE.getDriverSn().isEmpty()){
|
||||
//此处拦截是为了防止过程中乘客屏和司机端断连,拿不到司机端sn, 造成请求失败去刷新了界面
|
||||
return;
|
||||
}
|
||||
if (code == 1003){
|
||||
routesResult = null;
|
||||
cleanStation("queryDriverSiteByCoordinate 1003");
|
||||
return;
|
||||
}
|
||||
queryDriverByLocalDriver();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void clearLocalRouteResult() {
|
||||
if (routesResult != null) {
|
||||
routesResult = null;
|
||||
}
|
||||
mNextStationIndex = 0;
|
||||
cleanStation("queryDriverSiteByCoordinate");
|
||||
if (mRouteLineInfoCallback != null){
|
||||
mRouteLineInfoCallback.showNoTaskView();
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePassengerRouteInfo(BusRoutesResult result) {
|
||||
if (result == null){
|
||||
clearLocalRouteResult();
|
||||
return;
|
||||
}
|
||||
CallerLogger.d( M_BUS_P + TAG, "queryDriverSiteByCoordinate = update");
|
||||
routesResult = result;
|
||||
|
||||
if (mRouteLineInfoCallback != null){
|
||||
mRouteLineInfoCallback.updateLineInfo(result.getName());
|
||||
mRouteLineInfoCallback.hideNoTaskView();
|
||||
if (result.getSites() != null){
|
||||
List<BusStationBean> stations = result.getSites();
|
||||
mStations.clear();
|
||||
mStations.addAll(stations);
|
||||
for (int i = 0; i< stations.size(); i++){
|
||||
BusStationBean station = stations.get(i);
|
||||
if (station.getDrivingStatus() == STATION_STATUS_STOPPED && station.isLeaving() && i+1 < stations.size()){
|
||||
Logger.d(M_BUS_P + TAG, "order = station= leave");
|
||||
isGoingToNextStation = true;
|
||||
mRouteLineInfoCallback.updateStationsInfo(stations,i+1,false);
|
||||
mNextStationIndex = i+1;
|
||||
BusStationBean startStation = mStations.get(i);
|
||||
BusStationBean endStation = mStations.get(i+1);
|
||||
setTrajectoryStation(startStation, endStation, result.getLineId());
|
||||
return;
|
||||
}else if (station.getDrivingStatus() == STATION_STATUS_STOPPED && !station.isLeaving()){
|
||||
if (i == stations.size() - 1) {
|
||||
cleanStation("updatePassengerRouteInfo最后一个站点");
|
||||
}
|
||||
|
||||
isGoingToNextStation = false;
|
||||
Logger.d(M_BUS_P + TAG, "order = station= arrive");
|
||||
mRouteLineInfoCallback.updateStationsInfo(stations,i,true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void release() {
|
||||
releaseListeners();
|
||||
cleanStation("release");
|
||||
startOrStopOrderLoop(false);
|
||||
}
|
||||
|
||||
public void setMoGoAutopilotPlanningListener(IBusPassengerAutopilotPlanningCallback
|
||||
moGoAutopilotPlanningCallback) {
|
||||
this.mAutopilotPlanningCallback = moGoAutopilotPlanningCallback;
|
||||
}
|
||||
|
||||
public void setADASStatusCallback(IBusPassengerADASStatusCallback callback) {
|
||||
this.mADASStatusCallback = callback;
|
||||
}
|
||||
|
||||
public void setControllerStatusCallback(String tag, IBusPassengerControllerStatusCallback callback) {
|
||||
if (tag == null || "".equals(tag)) return;
|
||||
|
||||
if (callback == null) {
|
||||
mControllerStatusCallbackMap.remove(tag);
|
||||
return;
|
||||
}
|
||||
|
||||
mControllerStatusCallbackMap.put(tag,callback);
|
||||
|
||||
}
|
||||
|
||||
private void initListeners() {
|
||||
|
||||
// 2021.11.1重构自动驾驶 实现接口 IMoGoAutopilotStatusListener 注册监听 替换IMogoAdasOCHCallback接口
|
||||
OchAutoPilotStatusListenerManager.INSTANCE.addListener(TAG,mGoAutopilotStatusListener);
|
||||
IntentManager.getInstance().registerIntentListener(ConnectivityManager.CONNECTIVITY_ACTION, mNetWorkIntentListener );
|
||||
// 定位监听
|
||||
OchLocationManager.addGCJ02Listener(TAG, 3,mMapLocationListener);
|
||||
|
||||
|
||||
//监听司机端消息
|
||||
CallerTelematicListenerManager.INSTANCE.addListener(TAG,mReceivedMsgListener);
|
||||
|
||||
AbnormalFactorsLoopManager.INSTANCE.startLoopAbnormalFactors(mContext);
|
||||
TrajectoryAndDistanceManager.INSTANCE.addDistanceListener(TAG, trajectoryListener);
|
||||
}
|
||||
|
||||
private void releaseListeners() {
|
||||
|
||||
// 注销定位监听
|
||||
OchLocationManager.removeGCJ02Listener(TAG);
|
||||
|
||||
MogoAiCloudSocketManager.getInstance(mContext)
|
||||
.unregisterLifecycleListener(10010);
|
||||
|
||||
OchAutoPilotStatusListenerManager.INSTANCE.removeListener(mGoAutopilotStatusListener);
|
||||
|
||||
AbnormalFactorsLoopManager.INSTANCE.stopLoopAbnormalFactors();
|
||||
|
||||
CallerTelematicListenerManager.INSTANCE.removeListener(TAG);
|
||||
CallerTelematicListenerManager.INSTANCE.removeListener(TAG);
|
||||
}
|
||||
|
||||
private final IDistanceListener trajectoryListener = new IDistanceListener() {
|
||||
@Override
|
||||
public void stationDistanceCallback(float distance) {
|
||||
|
||||
}
|
||||
@Override
|
||||
public void distanceCallback(float distance) {
|
||||
double lastTime = distance / BusPassengerConst.BUS_AVERAGE_SPEED * 3.6; //秒
|
||||
CallerLogger.d(M_BUS_P + TAG, "轨迹排查==lastSumLength = "+distance);
|
||||
if(routesResult!=null){
|
||||
for (BusStationBean site : routesResult.getSites()) {
|
||||
if (site.getDrivingStatus() == BusPassengerConst.STATION_STATUS_STOPPED && !site.isLeaving()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 小于200m 播报站点介绍
|
||||
if(distance<200){
|
||||
BusStationBean stationNext = mStations.get(mNextStationIndex);
|
||||
if(!stationNext.isPlayTts()){
|
||||
if (!StringUtils.isEmpty(stationNext.getIntroduction())) {
|
||||
VoiceNotice.showNotice(stationNext.getIntroduction());
|
||||
stationNext.setPlayTts(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
mAutopilotPlanningCallback.routePlanningToNextStationChanged(
|
||||
(long)distance, (long)lastTime
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
private final IReceivedMsgListener mReceivedMsgListener = new IReceivedMsgListener() {
|
||||
@Override
|
||||
public void onDemoMode(boolean isDemoMode) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedServerSn(@Nullable String sn) {
|
||||
Logger.d(SceneConstant.M_BUS_P + TAG, "司机屏sn:"+sn );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedMsg(int type, @NonNull byte[] byteArray) {
|
||||
if (OchCommonConst.BUSINESS_STRING == type) {
|
||||
|
||||
BaseDPMsg baseMsg = GsonUtils.fromJson(new String(byteArray), BaseDPMsg.class);
|
||||
Logger.d(SceneConstant.M_BUS_P + TAG, "onReceivedMsg = " + GsonUtils.toJson(baseMsg));
|
||||
|
||||
if (baseMsg != null && baseMsg.getType() == DPMsgType.TYPE_COMMON.getType()) {
|
||||
AppConnectMsg msg = GsonUtils.fromJson(new String(byteArray), AppConnectMsg.class);
|
||||
if (msg != null && msg.isViewShow()) { //消息盒子显示内容
|
||||
OCHSocketMessageManager.INSTANCE.pushAppOperationalMsgBox(
|
||||
DateTimeUtil.getCurrentTimeStamp(), msg.getMsg(),
|
||||
OCHSocketMessageManager.OPERATION_SYSTEM);
|
||||
}
|
||||
} else if (baseMsg != null && baseMsg.getType() == DPMsgType.TYPE_TASK_DETAILS.getType()) {
|
||||
TaskDetailsMsg msg = GsonUtils.fromJson(new String(byteArray), TaskDetailsMsg.class);
|
||||
|
||||
Logger.d(SceneConstant.M_BUS_P + TAG, "onReceivedMsg = " + GsonUtils.toJson(msg));
|
||||
if (msg == null || msg.getMsg().isEmpty()) {
|
||||
clearLocalRouteResult();
|
||||
return;
|
||||
}
|
||||
BusTransferData result = GsonUtils.fromJson(msg.getMsg(), BusTransferData.class);
|
||||
if (msg != null && mDriverStatusCallback != null) {
|
||||
mDriverStatusCallback.changeOperationStatus(result.getLoginStatus() == 1);
|
||||
}
|
||||
if (result != null) { //已司机端传来的为准
|
||||
routesResult = result.getRoutesResult();
|
||||
updatePassengerRouteInfo(routesResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//监听网络变化,避免启动机器时无网导致无法更新订单信息
|
||||
private final IMogoIntentListener mNetWorkIntentListener = new IMogoIntentListener() {
|
||||
@Override
|
||||
public void onIntentReceived( String intentStr, Intent intent ) {
|
||||
CallerLogger.d( M_BUS_P + TAG, "onIntentReceived = %s", intentStr );
|
||||
if ( ConnectivityManager.CONNECTIVITY_ACTION.equals( intentStr ) ) {
|
||||
if ( NetworkUtils.isConnected( mContext ) ) {
|
||||
queryDriverOperationStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final IMoGoChassisLocationGCJ02Listener mMapLocationListener = new IMoGoChassisLocationGCJ02Listener() {
|
||||
@Override
|
||||
public void onChassisLocationGCJ02(@Nullable MogoLocation gnssInfo) {
|
||||
if (null == gnssInfo) return;
|
||||
for (IBusPassengerControllerStatusCallback callback :mControllerStatusCallbackMap.values()){
|
||||
callback.onCarLocationChanged(gnssInfo);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final IOchAutopilotStatusListener mGoAutopilotStatusListener = new IOchAutopilotStatusListener(){
|
||||
|
||||
@Override
|
||||
public void onAutopilotStatusResponse(int state) {
|
||||
if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING) {
|
||||
//2022.7.20 自动驾驶更换成带档位的
|
||||
if (mADASStatusCallback != null) mADASStatusCallback.onAutopilotRunning();
|
||||
} else{
|
||||
if (FunctionBuildConfig.isDemoMode &&
|
||||
mNextStationIndex>= 0 && mNextStationIndex <= mStations.size() - 1
|
||||
&& isGoingToNextStation){
|
||||
Logger.d(M_BUS_P + TAG, "FunctionBuildConfig.isDemoMode is true");
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE) {
|
||||
if (mADASStatusCallback != null) mADASStatusCallback.onAutopilotEnable();
|
||||
} else if (state == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE) {
|
||||
if (mADASStatusCallback != null) mADASStatusCallback.onAutopilotDisable();
|
||||
}else if (state == IMoGoAutopilotStatusListener.STATUS_PARALLEL_DRIVING){
|
||||
if (mADASStatusCallback != null) mADASStatusCallback.onAutopilotRunning();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void startOrStopOrderLoop(boolean start) {
|
||||
CallerLogger.d(M_BUS_P + TAG, "startOrStopOrderLoop() " + start);
|
||||
if (start) {
|
||||
BusPassengerModelLoopManager.getInstance().startQueryDriverLineLoop();
|
||||
} else {
|
||||
BusPassengerModelLoopManager.getInstance().stopQueryDriverLineLoop();
|
||||
}
|
||||
}
|
||||
|
||||
private void setTrajectoryStation(
|
||||
BusStationBean startStationInfo ,
|
||||
BusStationBean endStationInfo,
|
||||
int lineId
|
||||
) {
|
||||
MogoLocation startStation = new MogoLocation();
|
||||
startStation.setLongitude(startStationInfo.getGcjLon());
|
||||
startStation.setLatitude(startStationInfo.getGcjLat());
|
||||
MogoLocation endStation = new MogoLocation();
|
||||
endStation.setLongitude(endStationInfo.getGcjLon());
|
||||
endStation.setLatitude(endStationInfo.getGcjLat());
|
||||
TrajectoryAndDistanceManager.INSTANCE.setStationPoint(startStation, endStation, (long)lineId);
|
||||
}
|
||||
|
||||
private void cleanStation(String type) {
|
||||
CallerLogger.d(M_BUS_P + TAG, "清理站点:"+type);
|
||||
TrajectoryAndDistanceManager.INSTANCE.setStationPoint(null, null, -1L);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.mogo.och.shuttle.passenger.network;
|
||||
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
|
||||
import com.mogo.och.shuttle.passenger.model.BusPassengerModel;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS_P;
|
||||
import static com.mogo.och.shuttle.passenger.constant.BusPassengerConst.LOOP_DELAY;
|
||||
import static com.mogo.och.shuttle.passenger.constant.BusPassengerConst.LOOP_LINE_2S;
|
||||
|
||||
/**
|
||||
* Created on 2021/11/22
|
||||
*
|
||||
* 管理轮询逻辑(订单轮询、新单轮询、新单抢单结果轮询等等)
|
||||
*/
|
||||
public class BusPassengerModelLoopManager {
|
||||
|
||||
private static final String TAG = BusPassengerModelLoopManager.class.getSimpleName();
|
||||
|
||||
private static final class SingletonHolder {
|
||||
private static final BusPassengerModelLoopManager INSTANCE = new BusPassengerModelLoopManager();
|
||||
}
|
||||
|
||||
public static BusPassengerModelLoopManager getInstance() {
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
private Disposable mQueryLineDisposable; //心跳轮询
|
||||
|
||||
public void startQueryDriverLineLoop() {
|
||||
if (mQueryLineDisposable != null && !mQueryLineDisposable.isDisposed()) {
|
||||
return;
|
||||
}
|
||||
CallerLogger.i(M_BUS_P + TAG, "startQueryDriverLineLoop()");
|
||||
mQueryLineDisposable = Observable.interval(LOOP_DELAY,
|
||||
LOOP_LINE_2S, TimeUnit.MILLISECONDS)
|
||||
.map((aLong -> aLong + 1))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(aLong -> BusPassengerModel.getInstance().queryDriverSiteByCoordinate());
|
||||
}
|
||||
|
||||
public void stopQueryDriverLineLoop() {
|
||||
if (mQueryLineDisposable != null) {
|
||||
CallerLogger.i(M_BUS_P + TAG, "stopQueryDriverLineLoop()");
|
||||
mQueryLineDisposable.dispose();
|
||||
mQueryLineDisposable = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
package com.mogo.och.shuttle.passenger.presenter;
|
||||
|
||||
import static com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.M_BUS_P;
|
||||
|
||||
import android.os.Looper;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
|
||||
import com.mogo.commons.AbsMogoApplication;
|
||||
import com.mogo.commons.mvp.Presenter;
|
||||
import com.mogo.eagle.core.data.map.MogoLocation;
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener;
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger;
|
||||
import com.mogo.eagle.core.utilcode.util.UiThreadHandler;
|
||||
import com.mogo.och.shuttle.passenger.callback.IBusPassegerDriverStatusCallback;
|
||||
import com.mogo.och.shuttle.passenger.callback.IBusPassengerADASStatusCallback;
|
||||
import com.mogo.och.shuttle.passenger.callback.IBusPassengerAutopilotPlanningCallback;
|
||||
import com.mogo.och.shuttle.passenger.callback.IBusPassengerControllerStatusCallback;
|
||||
import com.mogo.och.shuttle.passenger.callback.IBusPassengerRouteLineInfoCallback;
|
||||
import com.mogo.och.shuttle.passenger.model.BusPassengerModel;
|
||||
import com.mogo.och.shuttle.passenger.ui.BusPassengerRouteFragment;
|
||||
import com.mogo.och.data.bean.BusStationBean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created on 2022/3/31
|
||||
*/
|
||||
public class BaseBusPassengerPresenter extends Presenter<BusPassengerRouteFragment> implements
|
||||
IBusPassengerADASStatusCallback, IBusPassengerControllerStatusCallback, IBusPassegerDriverStatusCallback, IBusPassengerRouteLineInfoCallback, IBusPassengerAutopilotPlanningCallback {
|
||||
private static final String TAG = BaseBusPassengerPresenter.class.getSimpleName();
|
||||
|
||||
public BaseBusPassengerPresenter(BusPassengerRouteFragment view) {
|
||||
super(view);
|
||||
BusPassengerModel.getInstance().init(AbsMogoApplication.getApp());
|
||||
initListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@NonNull LifecycleOwner owner) {
|
||||
super.onCreate(owner);
|
||||
CallerLogger.d(M_BUS_P + TAG, "Bus乘客端Presenter onCreate()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy(@NonNull LifecycleOwner owner) {
|
||||
super.onDestroy(owner);
|
||||
|
||||
releaseListeners();
|
||||
BusPassengerModel.getInstance().release();
|
||||
}
|
||||
|
||||
private void initListeners() {
|
||||
BusPassengerModel.getInstance().setADASStatusCallback(this);
|
||||
BusPassengerModel.getInstance().setControllerStatusCallback(TAG, this);
|
||||
BusPassengerModel.getInstance().setDriverStatusCallback(this);
|
||||
BusPassengerModel.getInstance().setRouteLineInfoCallback(this);
|
||||
BusPassengerModel.getInstance().setMoGoAutopilotPlanningListener(this);
|
||||
}
|
||||
|
||||
private void releaseListeners() {
|
||||
BusPassengerModel.getInstance().setADASStatusCallback(null);
|
||||
BusPassengerModel.getInstance().setControllerStatusCallback(TAG, null);
|
||||
BusPassengerModel.getInstance().setDriverStatusCallback(null);
|
||||
BusPassengerModel.getInstance().setRouteLineInfoCallback(null);
|
||||
BusPassengerModel.getInstance().setMoGoAutopilotPlanningListener(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAutopilotEnable() {
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mView != null) {
|
||||
mView.onAutopilotStatusChanged(
|
||||
IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_ENABLE);
|
||||
}
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAutopilotDisable() {
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mView != null) {
|
||||
mView.onAutopilotStatusChanged(
|
||||
IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_DISABLE);
|
||||
}
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAutopilotRunning() {
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mView != null) {
|
||||
mView.onAutopilotStatusChanged(
|
||||
IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING);
|
||||
}
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCarLocationChanged(MogoLocation location) {
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (location != null && mView != null) {
|
||||
mView.onCarLocationChanged(location);
|
||||
}
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeOperationStatus(boolean changeStatus) {
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mView != null) {
|
||||
mView.changeOperationStatus(changeStatus);
|
||||
}
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLineInfo(String lineName) {
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mView != null) {
|
||||
mView.updateLineInfo(lineName);
|
||||
}
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStationsInfo(List<BusStationBean> stations, int currentStationIndex, boolean isArrived) {
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mView != null) {
|
||||
mView.updateStationsInfo(stations, currentStationIndex, isArrived);
|
||||
}
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showNoTaskView() {
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mView != null) {
|
||||
mView.showNoTaskView();
|
||||
}
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideNoTaskView() {
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mView != null) {
|
||||
mView.hideNoTaskView();
|
||||
}
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void routePlanningToNextStationChanged(long meters, long timeInSecond) {
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mView != null) {
|
||||
mView.updateRoutePlanningToNextStation(meters, timeInSecond);
|
||||
}
|
||||
}
|
||||
}, UiThreadHandler.MODE.QUEUE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.mogo.och.shuttle.passenger.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import com.mogo.eagle.core.function.api.devatools.IMoGoDevaToolsListener
|
||||
import com.mogo.eagle.core.function.hmi.ui.widget.BlueToothView
|
||||
import com.mogo.eagle.core.utilcode.util.ThreadUtils
|
||||
import com.mogo.och.shuttle.passenger.R
|
||||
import kotlinx.android.synthetic.main.shuttle_p_jl_view_blue_tooth.view.blueView
|
||||
|
||||
/**
|
||||
* 魔戒蓝牙控件
|
||||
* 放置于StatusBar右侧位置
|
||||
*/
|
||||
class BusPBlueToothView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : BlueToothView(context, attrs, defStyleAttr),IMoGoDevaToolsListener {
|
||||
|
||||
init {
|
||||
LayoutInflater.from(context).inflate(R.layout.shuttle_p_weak_jl_view_blue_tooth, this, true)
|
||||
}
|
||||
|
||||
override fun mofangStatus(status: Boolean) {
|
||||
ThreadUtils.runOnUiThread {
|
||||
if (status) {
|
||||
blueView.setImageResource(R.drawable.shuttle_p_jl_blue_tooth_close)
|
||||
} else {
|
||||
blueView.setImageResource(R.drawable.shuttle_p_jl_blue_tooth_open)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.mogo.och.shuttle.passenger.ui
|
||||
|
||||
import android.annotation.*
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import com.mogo.eagle.core.function.api.hmi.view.IViewControlListener
|
||||
import com.mogo.eagle.core.function.api.setting.IMoGoSkinModeChangeListener
|
||||
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager
|
||||
import com.mogo.eagle.core.function.call.hmi.CallerHmiViewControlListenerManager
|
||||
import com.mogo.eagle.core.function.call.setting.CallerSkinModeListenerManager
|
||||
import com.mogo.eagle.core.utilcode.kotlin.*
|
||||
import com.mogo.eagle.core.utilcode.util.AppUtils
|
||||
import com.mogo.och.shuttle.passenger.R
|
||||
import kotlinx.android.synthetic.main.shuttle_p_jl_view_status_bar.view.tv_shuttle_b1_p_version
|
||||
import kotlinx.coroutines.*
|
||||
import me.jessyan.autosize.utils.AutoSizeUtils
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2023/2/14
|
||||
*/
|
||||
class BusPStatusBarView @JvmOverloads constructor(
|
||||
context: Context, attrs: AttributeSet? = null
|
||||
) : ConstraintLayout(context, attrs), IViewControlListener, IMoGoSkinModeChangeListener{
|
||||
|
||||
companion object {
|
||||
const val TAG = "BusPStatusBarView"
|
||||
}
|
||||
|
||||
init {
|
||||
LayoutInflater.from(context).inflate(R.layout.shuttle_p_weak_jl_view_status_bar, this, true)
|
||||
setBackgroundResource(R.drawable.shuttle_p_jl_bg_status_bar)
|
||||
isClickable = true
|
||||
isFocusable = true
|
||||
|
||||
tv_shuttle_b1_p_version.text = "版本:${AppUtils.getAppVersionName()}"
|
||||
}
|
||||
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onAttachedToWindow() {
|
||||
super.onAttachedToWindow()
|
||||
post {
|
||||
val params: ViewGroup.LayoutParams = getLayoutParams()
|
||||
params.height = AutoSizeUtils.dp2px(context,40f)
|
||||
layoutParams = params
|
||||
}
|
||||
//添加view控制
|
||||
CallerHmiViewControlListenerManager.addListener(TAG,this)
|
||||
// 添加换肤监听
|
||||
CallerSkinModeListenerManager.addListener(TAG, this)
|
||||
}
|
||||
|
||||
override fun onSkinModeChange(skinMode: Int) {
|
||||
when (skinMode) {
|
||||
0 -> setStatusBarDarkOrLight(false)
|
||||
1 -> setStatusBarDarkOrLight(true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
CallerHmiViewControlListenerManager.removeListener(TAG)
|
||||
CallerSkinModeListenerManager.removeListener(TAG)
|
||||
CallerDevaToolsManager.hideStatusBar()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package com.mogo.och.shuttle.passenger.ui;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.mogo.commons.mvp.IView;
|
||||
import com.mogo.commons.mvp.MvpFragment;
|
||||
|
||||
import com.mogo.commons.mvp.Presenter;
|
||||
import com.mogo.eagle.core.function.hmi.ui.widget.RomaPassengerView;
|
||||
import com.mogo.eagle.core.function.view.MapBizView;
|
||||
import com.mogo.och.shuttle.passenger.R;
|
||||
|
||||
/**
|
||||
* Created on 2022/3/31
|
||||
* <p>
|
||||
* Bus乘客端基础Fragment
|
||||
*/
|
||||
public abstract class BusPassengerBaseFragment<V extends IView, P extends Presenter<V>> extends MvpFragment<V, P> {
|
||||
private static final String TAG = BusPassengerBaseFragment.class.getSimpleName();
|
||||
|
||||
private MapBizView mapBizView;
|
||||
private FrameLayout flContainer;
|
||||
private RomaPassengerView romaPView;
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.shuttle_p_weak_jl_base_fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTagName() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initViews() {
|
||||
mapBizView = findViewById(R.id.mapBizView);
|
||||
|
||||
showRouteFragment();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initViews(Bundle savedInstanceState) {
|
||||
super.initViews(savedInstanceState);
|
||||
mapBizView.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mapBizView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
mapBizView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
mapBizView.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mapBizView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
mapBizView.onDestroy();
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取站点面板view,在{@link #initViews()}时候添加到container中
|
||||
*
|
||||
* @return 站点面板view
|
||||
*/
|
||||
public abstract int getStationPanelViewId();
|
||||
|
||||
/**
|
||||
* 显示线路信息
|
||||
*/
|
||||
public void showRouteFragment() {
|
||||
flContainer = findViewById(R.id.bus_p_route_panel);
|
||||
LayoutInflater.from(getContext()).inflate(getStationPanelViewId(), flContainer);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,383 @@
|
||||
package com.mogo.och.shuttle.passenger.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.AnimationDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.text.Html;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
import androidx.appcompat.widget.AppCompatTextView;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.constraintlayout.widget.Group;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.amap.api.maps.model.LatLng;
|
||||
import com.elegant.utils.UiThreadHandler;
|
||||
import com.mogo.eagle.core.data.enums.SidePattern;
|
||||
import com.mogo.eagle.core.data.map.MogoLocation;
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener;
|
||||
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager;
|
||||
import com.mogo.eagle.core.function.hmi.ui.setting.ToggleDebugView;
|
||||
import com.mogo.map.overlay.IMoGoOverlayManager;
|
||||
import com.mogo.och.common.module.utils.ResourcesUtils;
|
||||
import com.mogo.och.shuttle.passenger.R;
|
||||
import com.mogo.och.shuttle.passenger.ui.adapter.BusPassengerLineStationsAdapter;
|
||||
import com.mogo.och.shuttle.passenger.presenter.BaseBusPassengerPresenter;
|
||||
import com.mogo.och.shuttle.passenger.ui.layoutmanager.CenterLayoutManager;
|
||||
import com.mogo.och.common.module.wigets.mapdirectionview.MapDirectionView;
|
||||
import com.mogo.och.common.module.utils.NumberFormatUtil;
|
||||
import com.mogo.och.common.module.wigets.MarqueeTextView;
|
||||
import com.mogo.och.common.module.wigets.OCHGradientTextView;
|
||||
import com.mogo.och.data.bean.BusStationBean;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2022/4/12
|
||||
*/
|
||||
public class BusPassengerRouteFragment extends
|
||||
BusPassengerBaseFragment<BusPassengerRouteFragment, BaseBusPassengerPresenter> {
|
||||
|
||||
public static final String TAG = "BusPassengerRouteFragment";
|
||||
|
||||
private final List<BusStationBean> mStationsList = new ArrayList<>();
|
||||
|
||||
private OCHGradientTextView mSpeedTv;
|
||||
private ConstraintLayout mNoLineInfoView;
|
||||
private MarqueeTextView mLineName;
|
||||
private Group mRouteInfoView;
|
||||
private RecyclerView mStationsListRv;
|
||||
private MapDirectionView mMapDirectionView;
|
||||
private BusPassengerLineStationsAdapter mAdapter;
|
||||
private TextView emptyTv;
|
||||
private AppCompatImageView mAutopilotIv;
|
||||
private AppCompatTextView mCurrentArriveStation;
|
||||
private AppCompatTextView mCurrentArriveStationTitle;
|
||||
private AppCompatTextView mCurrentArriveTip;
|
||||
private AppCompatImageView mSpeakArrivedIv;
|
||||
|
||||
/**
|
||||
* 改变自动驾驶状态
|
||||
*
|
||||
* @param status 2 - running 1 - enable 2 - disable
|
||||
*/
|
||||
private int mPrevAPStatus = -1;
|
||||
|
||||
@Override
|
||||
public int getStationPanelViewId() {
|
||||
return R.layout.shuttle_p_weak_jl_route_fragment;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected BaseBusPassengerPresenter createPresenter() {
|
||||
return new BaseBusPassengerPresenter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initViews() {
|
||||
super.initViews();
|
||||
|
||||
mSpeedTv = findViewById(R.id.bus_p_speed_tv);
|
||||
mSpeedTv.setVertrial(true);
|
||||
mSpeedTv.setmColorList(new int[]{ResourcesUtils.getColor(R.color.shuttle_p_jl_speed_color_start),
|
||||
ResourcesUtils.getColor(R.color.shuttle_p_jl_speed_color_end)});
|
||||
|
||||
mNoLineInfoView =findViewById(R.id.bus_p_no_order_data_view);
|
||||
emptyTv = findViewById(R.id.no_order_data_tv);
|
||||
|
||||
mLineName = findViewById(R.id.bus_p_line_name_tv);
|
||||
mAutopilotIv = findViewById(R.id.auto_status_iv);
|
||||
mCurrentArriveStation = findViewById(R.id.bus_p_cur_station_name);
|
||||
mCurrentArriveStationTitle = findViewById(R.id.bus_p_cur_station_title);
|
||||
mCurrentArriveTip = findViewById(R.id.bus_p_cur_station_tip);
|
||||
mSpeakArrivedIv = findViewById(R.id.speak_arrived_iv);
|
||||
|
||||
mRouteInfoView = findViewById(R.id.bus_p_line_cl);
|
||||
mStationsListRv = findViewById(R.id.bus_p_line_stations_rl);
|
||||
|
||||
CenterLayoutManager manager = new CenterLayoutManager(getContext());
|
||||
mStationsListRv.setLayoutManager(manager);
|
||||
mAdapter = new BusPassengerLineStationsAdapter(getContext(), mStationsList);
|
||||
mStationsListRv.setAdapter(mAdapter);
|
||||
|
||||
mSpeedTv.setOnLongClickListener(v -> {
|
||||
Context context = getContext();
|
||||
if(context!=null){
|
||||
ToggleDebugView.Companion.
|
||||
getToggleDebugView().toggle(context, Gravity.RIGHT, SidePattern.RIGHT);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initViews(Bundle savedInstanceState) {
|
||||
super.initViews(savedInstanceState);
|
||||
mMapDirectionView = findViewById(R.id.bus_p_line_map_view);
|
||||
mMapDirectionView.onCreateView(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (mMapDirectionView != null) {
|
||||
mMapDirectionView.onResume();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
if (mMapDirectionView != null) {
|
||||
mMapDirectionView.onPause();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
if (mPresenter != null) {
|
||||
mPresenter.onDestroy(this);
|
||||
}
|
||||
IMoGoOverlayManager overlayManager = CallerMapUIServiceManager.INSTANCE.getOverlayManager();
|
||||
if(overlayManager!=null) {
|
||||
overlayManager.removeAllLines();
|
||||
overlayManager.removeAllPoints();
|
||||
}
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mMapDirectionView != null) {
|
||||
mMapDirectionView.onDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
public void clearMapView() {
|
||||
if (mMapDirectionView != null) {
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mMapDirectionView.clearPolyline();
|
||||
mMapDirectionView.clearCoordinatesLatLng();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void clearMapMarkers() {
|
||||
if (mMapDirectionView != null) {
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mMapDirectionView.clearLineMarkers();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void changeOperationStatus(boolean status) {
|
||||
if (!status) {
|
||||
emptyTv.setText(getString(R.string.shuttle_p_jl_no_out));
|
||||
mNoLineInfoView.setVisibility(View.VISIBLE);
|
||||
mRouteInfoView.setVisibility(View.GONE);
|
||||
mLineName.setText(getContext().getString(R.string.shuttle_p_jl_no_line));
|
||||
updateArrivedStation(null,0,true);
|
||||
clearMapView();
|
||||
clearMapMarkers();
|
||||
}
|
||||
}
|
||||
|
||||
public void showNoTaskView(){
|
||||
if (mNoLineInfoView.getVisibility() == View.GONE){
|
||||
mNoLineInfoView.setVisibility(View.VISIBLE);
|
||||
mRouteInfoView.setVisibility(View.GONE);
|
||||
mLineName.setText(getContext().getString(R.string.shuttle_p_jl_no_line));
|
||||
updateArrivedStation(null,0,true);
|
||||
clearMapView();
|
||||
clearMapMarkers();
|
||||
}
|
||||
emptyTv.setText(getString(R.string.shuttle_p_jl_no_task));
|
||||
}
|
||||
|
||||
public void hideNoTaskView(){
|
||||
if (mNoLineInfoView.getVisibility() == View.VISIBLE){
|
||||
mNoLineInfoView.setVisibility(View.GONE);
|
||||
}
|
||||
if (mRouteInfoView.getVisibility() == View.GONE){
|
||||
mRouteInfoView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateLineInfo(String lineName) {
|
||||
mLineName.setText(lineName);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param stations
|
||||
* @param currentStationIndex
|
||||
* @param isArrived 是否到站并离开,true 到达当前站 currentStationIndex 未离开, false 正在前往此站 currentStationIndex
|
||||
*/
|
||||
public void updateStationsInfo(List<BusStationBean> stations, int currentStationIndex, boolean isArrived) {
|
||||
updateArrivedStation(stations.get(currentStationIndex).getName(),currentStationIndex,isArrived);
|
||||
mStationsList.clear();
|
||||
mStationsList.addAll(stations);
|
||||
mAdapter.notifyDataSetChanged();
|
||||
|
||||
if (currentStationIndex > -1){
|
||||
updateCurrentStation(currentStationIndex);
|
||||
}
|
||||
|
||||
if (currentStationIndex == 0 && isArrived){ //到达始发站且并未出发, 恢复站点marker 清楚路径 清空路径点
|
||||
clearMapView();
|
||||
}
|
||||
|
||||
if (stations.size() > 0){
|
||||
updateWayPointList(stations,currentStationIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateWayPointList(List<BusStationBean> stations,int currentStationIndex) {
|
||||
List<LatLng> mLineStationsList = new ArrayList<>();
|
||||
for (int i = 0; i< stations.size(); i++) {//站点集合
|
||||
LatLng latLng = new LatLng(stations.get(i).getGcjLat(),stations.get(i).getGcjLon());// lat,lon
|
||||
mLineStationsList.add(latLng);
|
||||
}
|
||||
|
||||
if (mMapDirectionView != null) {
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mMapDirectionView.setLinePointMarkerAndDraw(mLineStationsList,currentStationIndex);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void onCameraChange(float bearing) {
|
||||
//// startIvCompass(bearing);
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * 设置指南针旋转
|
||||
// *
|
||||
// * @param bearing
|
||||
// */
|
||||
// private void startIvCompass(float bearing) {
|
||||
// bearing = 360 - bearing;
|
||||
// CallerLogger.d(M_BUS_P + TAG, "startIvCompass: " + bearing);
|
||||
// rotateAnimation = new RotateAnimation(lastBearing, bearing, Animation.RELATIVE_TO_SELF
|
||||
// , 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
|
||||
// rotateAnimation.setFillAfter(true);
|
||||
//
|
||||
// mMapArrowIcon.startAnimation(rotateAnimation);
|
||||
// lastBearing = bearing;
|
||||
// }
|
||||
|
||||
public void onCarLocationChanged(MogoLocation location) {
|
||||
updateSpeedView((float) location.getGnssSpeed());
|
||||
}
|
||||
|
||||
public void updateSpeedView(float speed){
|
||||
int speedKM = (int) (Math.abs(speed) * 3.6F);
|
||||
mSpeedTv.setText(String.valueOf(speedKM));
|
||||
}
|
||||
|
||||
public void updateCurrentStation(int position) {
|
||||
if (mStationsListRv != null){
|
||||
mStationsListRv.smoothScrollToPosition(position);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateArrivedStation(String station,int currentIndex,boolean isArrived){
|
||||
if (null == station){
|
||||
mCurrentArriveStation.setText("----");
|
||||
mCurrentArriveStationTitle.setText(ResourcesUtils.getString(R.string.shuttle_p_jl_cur_station_title));
|
||||
mCurrentArriveTip.setText(ResourcesUtils.getString(R.string.shuttle_p_jl_cur_station_arrived_tip));
|
||||
mCurrentArriveTip.setBackgroundResource(R.drawable.shuttle_p_jl_cur_station_arrived_bg);
|
||||
handleArrivingSpeakIconDrawable();
|
||||
}else {
|
||||
mCurrentArriveStation.setText(station);
|
||||
if (currentIndex == 0){
|
||||
mCurrentArriveStationTitle.setText(ResourcesUtils.getString(R.string.shuttle_p_jl_cur_station_title));
|
||||
mCurrentArriveTip.setText(ResourcesUtils.getString(R.string.shuttle_p_jl_cur_station_arrived_tip));
|
||||
mCurrentArriveTip.setBackgroundResource(R.drawable.shuttle_p_jl_cur_station_arrived_bg);
|
||||
handleArrivingSpeakIconDrawable();
|
||||
return;
|
||||
}
|
||||
if (isArrived){
|
||||
mCurrentArriveStationTitle.setText(ResourcesUtils.getString(R.string.shuttle_p_jl_cur_station_title));
|
||||
mCurrentArriveTip.setText(ResourcesUtils.getString(R.string.shuttle_p_jl_cur_station_arrived_tip));
|
||||
mCurrentArriveTip.setBackgroundResource(R.drawable.shuttle_p_jl_cur_station_arrived_bg);
|
||||
handleArrivedSpeakIconDrawable();
|
||||
}else {
|
||||
mCurrentArriveStationTitle.setText(ResourcesUtils.getString(R.string.shuttle_p_jl_cur_next_station_title));
|
||||
mCurrentArriveTip.setBackgroundResource(R.drawable.shuttle_p_jl_cur_station_un_arrived_bg);
|
||||
handleArrivingSpeakIconDrawable();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void handleArrivedSpeakIconDrawable(){
|
||||
AnimationDrawable animationDrawable = (AnimationDrawable) mSpeakArrivedIv.getDrawable();
|
||||
animationDrawable.start();
|
||||
mSpeakArrivedIv.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
private void handleArrivingSpeakIconDrawable(){
|
||||
AnimationDrawable animationDrawable = (AnimationDrawable) mSpeakArrivedIv.getDrawable();
|
||||
animationDrawable.stop();
|
||||
mSpeakArrivedIv.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
public void updateRoutePlanningToNextStation(long meters, long timeInSecond){
|
||||
//更新进度条
|
||||
String dis = "0";
|
||||
String disUnit = "公里";
|
||||
if (meters > 0){
|
||||
if (meters / 1000 < 1){
|
||||
disUnit = "米";
|
||||
dis = String.valueOf(Math.round(meters));
|
||||
}else {
|
||||
disUnit = "公里";
|
||||
dis = NumberFormatUtil.formatLong((double)meters / 1000);
|
||||
}
|
||||
}
|
||||
// String strHtml2 = "<font color=\"#2D3E5F\">距离 </font>" + "<b><font color=\"#0043FF\">" + dis + "</font></b>" + "<font color=\"#2D3E5F\"> "+disUnit+"</font>"
|
||||
// + "<font color=\"#2D3E5F\">   剩余 </font>" + "<b><font color=\"#0043FF\">" + (int)Math.ceil((double)timeInSecond/ 60f) + "</font></b>" + "<font color=\"#2D3E5F\"> 分钟</font>";
|
||||
String str = dis+disUnit+" | "+(int)Math.ceil((double)timeInSecond/ 60f)+"分钟";
|
||||
mCurrentArriveTip.setText(Html.fromHtml(str));
|
||||
}
|
||||
|
||||
public void onAutopilotStatusChanged(int status) {
|
||||
UiThreadHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// 3. 其他过程直接更新
|
||||
if (mPrevAPStatus != status){
|
||||
AutopilotStatusChanged(status);
|
||||
}
|
||||
mPrevAPStatus = status;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void AutopilotStatusChanged(int status) {
|
||||
if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING == status) {
|
||||
mAutopilotIv.setImageResource(R.drawable.shuttle_p_jl_auto_open);
|
||||
} else {
|
||||
mAutopilotIv.setImageResource(R.drawable.shuttle_p_jl_auto_close);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
package com.mogo.och.shuttle.passenger.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.LinearLayout
|
||||
import com.mogo.eagle.core.data.enums.DataSourceType
|
||||
import com.mogo.eagle.core.data.enums.TrafficLightEnum
|
||||
import com.mogo.eagle.core.function.api.datacenter.union.IMoGoTrafficLightListener
|
||||
import com.mogo.eagle.core.function.call.v2x.CallerTrafficLightListenerManager
|
||||
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
|
||||
import com.mogo.och.shuttle.passenger.R
|
||||
import kotlinx.android.synthetic.main.shuttle_p_jl_traffic_light_view.view.bus_p_traffic_light_bg
|
||||
import kotlinx.android.synthetic.main.shuttle_p_jl_traffic_light_view.view.bus_p_traffic_light_iv
|
||||
import kotlinx.android.synthetic.main.shuttle_p_jl_traffic_light_view.view.bus_p_traffic_light_time_tv
|
||||
|
||||
/**
|
||||
* bus乘客端:红绿灯view
|
||||
*
|
||||
* Created on 2022/3/14
|
||||
*/
|
||||
class BusPassengerTrafficLightView @JvmOverloads constructor(
|
||||
context: Context?,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : LinearLayout(context, attrs, defStyleAttr), IMoGoTrafficLightListener {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "BusPassengerTrafficLightView"
|
||||
}
|
||||
|
||||
private var mCurrentLightId = TrafficLightEnum.BLACK
|
||||
|
||||
init {
|
||||
init(context)
|
||||
}
|
||||
|
||||
private fun init(context: Context?) {
|
||||
LayoutInflater.from(context).inflate(R.layout.shuttle_p_weak_jl_traffic_light_view, this, true)
|
||||
}
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
super.onAttachedToWindow()
|
||||
CallerTrafficLightListenerManager.addListener(TAG, this)
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
CallerTrafficLightListenerManager.removeListener(TAG)
|
||||
}
|
||||
|
||||
/**
|
||||
* 展示红绿灯预警
|
||||
*
|
||||
* @param checkLightId 0-都是默认,1-红,2-黄,3-绿
|
||||
* @param lightSource 1:云端下发;2:自车感知
|
||||
*/
|
||||
override fun showTrafficLight(checkLightId: TrafficLightEnum, lightSource: DataSourceType) {
|
||||
super.showTrafficLight(checkLightId, lightSource)
|
||||
mCurrentLightId = checkLightId
|
||||
updateTrafficLightIcon(checkLightId)
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭红绿灯预警展示,并重制灯态
|
||||
*/
|
||||
override fun disableTrafficLight() {
|
||||
super.disableTrafficLight()
|
||||
UiThreadHandler.post {
|
||||
mCurrentLightId = TrafficLightEnum.BLACK
|
||||
this@BusPassengerTrafficLightView.visibility = GONE
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param redNum 红灯倒计时
|
||||
* @param yellowNum 黄灯倒计时
|
||||
* @param greenNum 绿灯倒计时
|
||||
*/
|
||||
override fun changeCountdownTrafficLightNum(redNum: Int, yellowNum: Int, greenNum: Int) {
|
||||
super.changeCountdownTrafficLightNum(redNum, yellowNum, greenNum)
|
||||
resetView()
|
||||
when (mCurrentLightId) {
|
||||
TrafficLightEnum.RED -> changeCountdownRed(redNum)
|
||||
TrafficLightEnum.YELLOW -> changeCountdownYellow(yellowNum)
|
||||
TrafficLightEnum.GREEN -> changeCountdownGreen(greenNum)
|
||||
else -> UiThreadHandler.post { bus_p_traffic_light_time_tv.text = "" }
|
||||
}
|
||||
}
|
||||
|
||||
override fun changeCountdownRed(redNum: Int) {
|
||||
super.changeCountdownRed(redNum)
|
||||
UiThreadHandler.post {
|
||||
if (redNum > 0) {
|
||||
resetView()
|
||||
bus_p_traffic_light_time_tv.text = redNum.toString()
|
||||
} else {
|
||||
disableTrafficLightCountDown()
|
||||
bus_p_traffic_light_time_tv.text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun changeCountdownGreen(greenNum: Int) {
|
||||
super.changeCountdownGreen(greenNum)
|
||||
UiThreadHandler.post {
|
||||
if (greenNum > 0) {
|
||||
resetView()
|
||||
bus_p_traffic_light_time_tv.text = greenNum.toString()
|
||||
} else {
|
||||
disableTrafficLightCountDown()
|
||||
bus_p_traffic_light_time_tv.text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun changeCountdownYellow(yellowNum: Int) {
|
||||
super.changeCountdownYellow(yellowNum)
|
||||
UiThreadHandler.post {
|
||||
if (yellowNum > 0) {
|
||||
resetView()
|
||||
bus_p_traffic_light_time_tv.text = yellowNum.toString()
|
||||
} else {
|
||||
disableTrafficLightCountDown()
|
||||
bus_p_traffic_light_time_tv.text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新红绿灯icon
|
||||
*
|
||||
* @param lightId 0-都是默认,1-红,2-黄,3-绿
|
||||
*/
|
||||
private fun updateTrafficLightIcon(lightId: TrafficLightEnum) {
|
||||
UiThreadHandler.post {
|
||||
when (lightId) {
|
||||
TrafficLightEnum.RED -> {
|
||||
bus_p_traffic_light_iv.setBackgroundResource(R.drawable.shuttle_p_jl_light_red_nor)
|
||||
this@BusPassengerTrafficLightView.visibility = VISIBLE
|
||||
}
|
||||
TrafficLightEnum.YELLOW -> {
|
||||
bus_p_traffic_light_iv.setBackgroundResource(R.drawable.shuttle_p_jl_light_yellow_nor)
|
||||
this@BusPassengerTrafficLightView.visibility = VISIBLE
|
||||
}
|
||||
TrafficLightEnum.GREEN -> {
|
||||
bus_p_traffic_light_iv.setBackgroundResource(R.drawable.shuttle_p_jl_light_green_nor)
|
||||
this@BusPassengerTrafficLightView.visibility = VISIBLE
|
||||
}
|
||||
else -> this@BusPassengerTrafficLightView.visibility = GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun disableTrafficLightCountDown() {
|
||||
super.disableTrafficLightCountDown()
|
||||
UiThreadHandler.post {
|
||||
val layoutParams = layoutParams
|
||||
if (layoutParams is MarginLayoutParams) {
|
||||
val lp = layoutParams
|
||||
lp.width = resources.getDimension(R.dimen.shuttle_p_jl_traffic_light_icon_size).toInt()
|
||||
setLayoutParams(lp)
|
||||
bus_p_traffic_light_time_tv.visibility = GONE
|
||||
bus_p_traffic_light_bg.layoutParams.width =
|
||||
resources.getDimension(R.dimen.dp_90).toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun resetView() {
|
||||
val layoutParams = layoutParams
|
||||
if (layoutParams is MarginLayoutParams) {
|
||||
val lp = layoutParams
|
||||
lp.width = resources.getDimension(R.dimen.shuttle_p_jl_route_traffic_light_view_width).toInt()
|
||||
setLayoutParams(lp)
|
||||
bus_p_traffic_light_time_tv.visibility = VISIBLE
|
||||
bus_p_traffic_light_bg.layoutParams.width =
|
||||
resources.getDimension(R.dimen.shuttle_p_jl_traffic_light_bg_width).toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package com.mogo.och.shuttle.passenger.ui.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.mogo.och.shuttle.passenger.R;
|
||||
import com.mogo.och.common.module.utils.BlinkAnimationUtil;
|
||||
import com.mogo.och.common.module.wigets.MarqueeTextView;
|
||||
import com.mogo.och.data.bean.BusStationBean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.mogo.och.shuttle.passenger.constant.BusPassengerConst.STATION_STATUS_ARRIVING;
|
||||
import static com.mogo.och.shuttle.passenger.constant.BusPassengerConst.STATION_STATUS_LEAVING;
|
||||
import static com.mogo.och.shuttle.passenger.constant.BusPassengerConst.STATION_STATUS_STOPPED;
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2022/4/6
|
||||
*/
|
||||
public class BusPassengerLineStationsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||
|
||||
private Context mContext;
|
||||
private List<BusStationBean> mStations;
|
||||
|
||||
public BusPassengerLineStationsAdapter(Context context, List<BusStationBean> stations){
|
||||
this.mContext = context;
|
||||
this.mStations = stations;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(mContext).inflate(R.layout.shuttle_p_weak_jl_stations_common_item,parent,false);
|
||||
StationViewHolder viewHolder = new StationViewHolder(view);
|
||||
return viewHolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||
BusStationBean station = mStations.get(position);
|
||||
StationViewHolder viewHolder = (StationViewHolder)holder;
|
||||
viewHolder.stationName.setText(station.getName());
|
||||
BlinkAnimationUtil.clearAnimation(viewHolder.stationCircle);
|
||||
if (position == 0){ //第一个 起点
|
||||
viewHolder.curArrowBg.setVisibility(View.GONE);
|
||||
viewHolder.curArrowBottomBg.setVisibility(View.VISIBLE);
|
||||
Log.d("onBindViewHolder" , "position0 = "+position);
|
||||
viewHolder.stationCircle.setImageResource(R.drawable.shuttle_p_jl_bg_start_tag_bg);
|
||||
if (station.getDrivingStatus() == STATION_STATUS_STOPPED && !station.isLeaving()){//到达未离开
|
||||
viewHolder.stationName.setTextColor(mContext.getResources().getColor(R.color.shuttle_p_jl_clock_17417B));
|
||||
BlinkAnimationUtil.setAnimation(viewHolder.stationCircle);
|
||||
viewHolder.stationName.setEllipsize(TextUtils.TruncateAt.MARQUEE);
|
||||
viewHolder.curArrowBottomBg.setBackgroundColor(mContext.getColor(R.color.shuttle_p_jl_clock_1F82FB));
|
||||
}else {
|
||||
viewHolder.stationName.setTextColor(mContext.getResources().getColor(R.color.shuttle_p_jl_clock_992D3E5F));
|
||||
viewHolder.stationName.setEllipsize(TextUtils.TruncateAt.END);
|
||||
viewHolder.curArrowBottomBg.setBackgroundColor(mContext.getColor(R.color.shuttle_p_jl_clock_A9B6CA));
|
||||
}
|
||||
}else{
|
||||
viewHolder.curArrowBg.setVisibility(View.VISIBLE);
|
||||
viewHolder.curArrowBottomBg.setVisibility(View.VISIBLE);
|
||||
BusStationBean preStation = mStations.get(position -1);
|
||||
if (station.getDrivingStatus() == STATION_STATUS_LEAVING ||
|
||||
(station.getDrivingStatus() == STATION_STATUS_STOPPED && station.isLeaving())){ //过站
|
||||
viewHolder.stationName.setTextColor(mContext.getResources().getColor(R.color.shuttle_p_jl_clock_992D3E5F));
|
||||
viewHolder.curArrowBg.setBackgroundColor(mContext.getColor(R.color.shuttle_p_jl_clock_A9B6CA));
|
||||
viewHolder.curArrowBottomBg.setBackgroundColor(mContext.getColor(R.color.shuttle_p_jl_clock_A9B6CA));
|
||||
viewHolder.stationCircle.setImageResource(R.drawable.shuttle_p_jl_point_gray);
|
||||
viewHolder.stationName.setEllipsize(TextUtils.TruncateAt.END);
|
||||
Log.d("onBindViewHolder" , "position 1 = "+position);
|
||||
} else if (station.getDrivingStatus() == STATION_STATUS_STOPPED && !station.isLeaving()){//刚到站未离开的
|
||||
viewHolder.stationName.setTextColor(mContext.getResources().getColor(R.color.shuttle_p_jl_clock_17417B));
|
||||
viewHolder.curArrowBg.setBackgroundColor(mContext.getColor(R.color.shuttle_p_jl_clock_A9B6CA));
|
||||
viewHolder.curArrowBottomBg.setBackgroundColor(mContext.getColor(R.color.shuttle_p_jl_clock_1F82FB));
|
||||
viewHolder.stationCircle.setImageResource(R.drawable.shuttle_p_jl_arrive_line_green);
|
||||
if (position == mStations.size() - 1){
|
||||
viewHolder.stationCircle.setImageResource(R.drawable.shuttle_p_jl_bg_end_tag_bg);
|
||||
viewHolder.curArrowBottomBg.setVisibility(View.GONE);
|
||||
}
|
||||
Log.d("onBindViewHolder" , "position2 = "+position);
|
||||
BlinkAnimationUtil.setAnimation(viewHolder.stationCircle);
|
||||
viewHolder.stationName.setEllipsize(TextUtils.TruncateAt.MARQUEE);
|
||||
}else if (station.getDrivingStatus() == STATION_STATUS_ARRIVING && preStation.isLeaving()){//即将到站
|
||||
viewHolder.stationName.setTextColor(mContext.getResources().getColor(R.color.shuttle_p_jl_panel_cur_station_tips_color));
|
||||
viewHolder.curArrowBg.setBackgroundColor(mContext.getColor(R.color.shuttle_p_jl_clock_A9B6CA));
|
||||
viewHolder.curArrowBottomBg.setBackgroundColor(mContext.getColor(R.color.shuttle_p_jl_clock_1F82FB));
|
||||
viewHolder.stationCircle.setImageResource(R.drawable.shuttle_p_jl_arrive_line_blue);
|
||||
Log.d("onBindViewHolder" , "position3 = "+position);
|
||||
|
||||
if (position == mStations.size() - 1){
|
||||
viewHolder.curArrowBottomBg.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
}else if (station.getDrivingStatus() == STATION_STATUS_ARRIVING &&
|
||||
(preStation.getDrivingStatus() == STATION_STATUS_ARRIVING
|
||||
|| preStation.getDrivingStatus() == STATION_STATUS_STOPPED)){ //未到站的并且前面也是未到站或者刚到站的
|
||||
viewHolder.stationName.setTextColor(mContext.getResources().getColor(R.color.shuttle_p_jl_panel_cur_station_tips_color));
|
||||
viewHolder.curArrowBg.setBackgroundColor(mContext.getColor(R.color.shuttle_p_jl_clock_1F82FB));
|
||||
viewHolder.curArrowBottomBg.setBackgroundColor(mContext.getColor(R.color.shuttle_p_jl_clock_1F82FB));
|
||||
viewHolder.stationCircle.setImageResource(R.drawable.shuttle_p_jl_point_blue);
|
||||
viewHolder.stationName.setEllipsize(TextUtils.TruncateAt.END);
|
||||
|
||||
if (position == mStations.size() - 1){
|
||||
viewHolder.stationCircle.setImageResource(R.drawable.shuttle_p_jl_bg_end_tag_bg);
|
||||
viewHolder.curArrowBottomBg.setVisibility(View.GONE);
|
||||
}
|
||||
Log.d("onBindViewHolder" , "position4 = "+position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mStations.size();
|
||||
}
|
||||
}
|
||||
class StationViewHolder extends RecyclerView.ViewHolder{
|
||||
public MarqueeTextView stationName;
|
||||
public ImageView stationCircle;
|
||||
public ImageView curArrowBg;
|
||||
public ImageView curArrowBottomBg;
|
||||
public StationViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
stationName = itemView.findViewById(R.id.bus_p_station);
|
||||
stationCircle = itemView.findViewById(R.id.bus_p_circle);
|
||||
curArrowBg = itemView.findViewById(R.id.bus_p_cur_arrow_bg);
|
||||
curArrowBottomBg = itemView.findViewById(R.id.bus_p_cur_arrow_bottom_bg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.mogo.och.shuttle.passenger.ui.layoutmanager;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.LinearSmoothScroller;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class CenterLayoutManager extends LinearLayoutManager {
|
||||
public CenterLayoutManager(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public CenterLayoutManager(Context context, int orientation, boolean reverseLayout) {
|
||||
super(context, orientation, reverseLayout);
|
||||
}
|
||||
|
||||
public CenterLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
|
||||
RecyclerView.SmoothScroller smoothScroller = new CenterSmoothScroller(recyclerView.getContext());
|
||||
smoothScroller.setTargetPosition(position);
|
||||
startSmoothScroll(smoothScroller);
|
||||
}
|
||||
|
||||
private static class CenterSmoothScroller extends LinearSmoothScroller {
|
||||
|
||||
CenterSmoothScroller(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int snapPreference) {
|
||||
return (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
package com.mogo.och.shuttle.passenger.ui.widget
|
||||
|
||||
import android.animation.AnimatorSet
|
||||
import android.animation.ObjectAnimator
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.animation.AlphaAnimation
|
||||
import android.view.animation.Animation
|
||||
import android.widget.ImageView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import com.mogo.eagle.core.function.api.datacenter.union.IMoGoTurnLightListener
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLamplightListenerManager
|
||||
import com.mogo.eagle.core.function.call.v2x.CallerTurnLightListenerManager
|
||||
import com.mogo.eagle.core.utilcode.util.ThreadUtils
|
||||
import com.mogo.och.shuttle.passenger.R
|
||||
import com.mogo.och.common.module.manager.light.TurnLightManager
|
||||
import kotlinx.android.synthetic.main.shuttle_p_jl_turn_light_status.view.left_nor_image
|
||||
import kotlinx.android.synthetic.main.shuttle_p_jl_turn_light_status.view.left_select_image
|
||||
import kotlinx.android.synthetic.main.shuttle_p_jl_turn_light_status.view.right_nor_image
|
||||
import kotlinx.android.synthetic.main.shuttle_p_jl_turn_light_status.view.right_select_image
|
||||
import kotlinx.android.synthetic.main.shuttle_p_jl_turn_light_status.view.turn_light_layout
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2023/2/13
|
||||
*/
|
||||
class BusPTurnLightView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : ConstraintLayout(context, attrs, defStyleAttr),
|
||||
IMoGoTurnLightListener, TurnLightManager.TurnLightListener {
|
||||
|
||||
|
||||
companion object {
|
||||
private const val TAG = "TurnLightViewStatus"
|
||||
}
|
||||
|
||||
private var isLeftLight: Boolean = false
|
||||
private var isRightLight: Boolean = false
|
||||
private var isDisappear: Boolean = false
|
||||
|
||||
init {
|
||||
LayoutInflater.from(context)
|
||||
.inflate(R.layout.shuttle_p_weak_jl_turn_light_status, this, true)
|
||||
}
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
super.onAttachedToWindow()
|
||||
CallerTurnLightListenerManager.addListener(TAG,this)
|
||||
|
||||
TurnLightManager.addTurnLightStatusChangeListener(TAG,this)
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
CallerChassisLamplightListenerManager.removeListener(TAG)
|
||||
CallerTurnLightListenerManager.removeListener(TAG)
|
||||
TurnLightManager.removeTurnLightStatusChangeListener(TAG)
|
||||
}
|
||||
|
||||
override fun hideTurnLightView() {
|
||||
ThreadUtils.runOnUiThread{
|
||||
if (!isDisappear) {
|
||||
isDisappear = true
|
||||
isLeftLight = false
|
||||
isRightLight = false
|
||||
animationDisappear()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun statusChange(newStatus: TurnLightManager.TurnLightStatus) {
|
||||
ThreadUtils.runOnUiThread {
|
||||
setTurnLight(newStatus)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转向灯动画
|
||||
*/
|
||||
private fun setTurnLight(directionLight: TurnLightManager.TurnLightStatus) {
|
||||
if (!isAttachedToWindow) {
|
||||
return
|
||||
}
|
||||
//根据左右进行显示和隐藏,实际要判断每个来的时间和频度
|
||||
when (directionLight) {
|
||||
TurnLightManager.TurnLightStatus.TURN_LIGHT_LEFT -> { //左转向
|
||||
if (!isLeftLight) {
|
||||
isLeftLight = true
|
||||
isRightLight = false
|
||||
isDisappear = false
|
||||
showNormalAnimation()
|
||||
left_select_image.visibility = View.VISIBLE
|
||||
right_select_image.visibility = View.GONE
|
||||
right_select_image.clearAnimation()
|
||||
setAnimation(left_select_image)
|
||||
}
|
||||
}
|
||||
TurnLightManager.TurnLightStatus.TURN_LIGHT_RIGHT -> { //右转向
|
||||
if (!isRightLight) {
|
||||
isRightLight = true
|
||||
isLeftLight = false
|
||||
isDisappear = false
|
||||
showNormalAnimation()
|
||||
left_select_image.visibility = View.GONE
|
||||
right_select_image.visibility = View.VISIBLE
|
||||
left_select_image.clearAnimation()
|
||||
setAnimation(right_select_image)
|
||||
}
|
||||
}
|
||||
TurnLightManager.TurnLightStatus.TURN_LIGHT_NONE -> { //消失
|
||||
if (!isDisappear) {
|
||||
isDisappear = true
|
||||
isLeftLight = false
|
||||
isRightLight = false
|
||||
animationDisappear()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//显示背景
|
||||
private fun showNormalAnimation() {
|
||||
val appearAnimation = AlphaAnimation(0f, 1.0f)
|
||||
appearAnimation.duration = 300
|
||||
val appearAnimationImage = AlphaAnimation(0f, 1.0f)
|
||||
appearAnimation.duration = 500
|
||||
turn_light_layout.startAnimation(appearAnimation)
|
||||
left_nor_image.startAnimation(appearAnimationImage)
|
||||
right_nor_image.startAnimation(appearAnimationImage)
|
||||
|
||||
turn_light_layout.visibility = View.VISIBLE
|
||||
left_nor_image.visibility = View.VISIBLE
|
||||
right_nor_image.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
//消失动画,当转向等数据为空时候
|
||||
private fun animationDisappear() {
|
||||
left_select_image.visibility = View.GONE
|
||||
right_select_image.visibility = View.GONE
|
||||
left_select_image.clearAnimation()
|
||||
right_select_image.clearAnimation()
|
||||
|
||||
left_nor_image.clearAnimation()
|
||||
right_nor_image.clearAnimation()
|
||||
turn_light_layout.clearAnimation()
|
||||
|
||||
val disappearAnimationLeft = AlphaAnimation(1.0f, 0f)
|
||||
disappearAnimationLeft.duration = 300
|
||||
|
||||
val disappearAnimationBg = AlphaAnimation(1.0f, 0f)
|
||||
disappearAnimationBg.duration = 500
|
||||
|
||||
left_nor_image.startAnimation(disappearAnimationLeft)
|
||||
right_nor_image.startAnimation(disappearAnimationLeft)
|
||||
turn_light_layout.startAnimation(disappearAnimationBg)
|
||||
|
||||
disappearAnimationLeft.setAnimationListener(object : Animation.AnimationListener {
|
||||
override fun onAnimationRepeat(p0: Animation?) {
|
||||
}
|
||||
|
||||
override fun onAnimationStart(p0: Animation?) {
|
||||
}
|
||||
|
||||
override fun onAnimationEnd(p0: Animation?) {
|
||||
left_nor_image.visibility = View.GONE
|
||||
right_nor_image.visibility = View.GONE
|
||||
}
|
||||
})
|
||||
|
||||
disappearAnimationBg.setAnimationListener(object : Animation.AnimationListener {
|
||||
override fun onAnimationRepeat(p0: Animation?) {
|
||||
}
|
||||
|
||||
override fun onAnimationStart(p0: Animation?) {
|
||||
}
|
||||
|
||||
override fun onAnimationEnd(p0: Animation?) {
|
||||
turn_light_layout.visibility = View.GONE
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//实现图片闪烁效果
|
||||
private fun setAnimation(imageView: ImageView) {
|
||||
val animationSet = AnimatorSet()
|
||||
val valueAnimator = ObjectAnimator.ofFloat(imageView, "alpha", 0f, 1.0f)
|
||||
val valueAnimatorDisappear = ObjectAnimator.ofFloat(imageView, "alpha", 1.0f, 0f)
|
||||
valueAnimator.duration = 1000
|
||||
valueAnimatorDisappear.duration = 800
|
||||
valueAnimator.repeatCount = -1
|
||||
valueAnimatorDisappear.repeatCount = -1
|
||||
animationSet.playTogether(valueAnimatorDisappear, valueAnimator)
|
||||
animationSet.start()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.mogo.och.shuttle.passenger.callback
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2023/2/15
|
||||
*/
|
||||
interface ADASCallback {
|
||||
fun updateHDMapStations(stations: MutableList<MutableList<Double>>)
|
||||
fun removeHDMapStations()
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.mogo.och.shuttle.passenger.callback
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2023/2/13
|
||||
*/
|
||||
interface AutoPilotStatusCallback {
|
||||
/**
|
||||
* false: 未开启自驾, true : 开启自驾
|
||||
*/
|
||||
fun updateAutoStatus(isOpen: Boolean)
|
||||
|
||||
fun updateAutoStatus(status: Int)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.mogo.och.shuttle.passenger.callback
|
||||
|
||||
import com.mogo.och.data.bean.BusStationBean
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2023/2/2
|
||||
*/
|
||||
interface DrivingInfoCallback {
|
||||
fun updateSpeed(speed: Int)
|
||||
fun updatePlateNumber(carNum: String)
|
||||
fun updateLine(lineName: String, lineDuring: String)
|
||||
fun updateRemainMT(meters : Long, timeInSecond : Long) // 米,秒
|
||||
fun changeOperationStatus(loginStatus : Boolean)
|
||||
fun showNoTaskView(isTrue : Boolean)
|
||||
fun updateLineStations(stations: MutableList<BusStationBean>)
|
||||
fun updateStationsInfo(stations: MutableList<BusStationBean>, i: Int, isArrived: Boolean)
|
||||
fun clearCustomPolyline()
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.mogo.och.shuttle.passenger.constant
|
||||
|
||||
/**
|
||||
* Created on 2021/12/6
|
||||
*/
|
||||
class M2Const {
|
||||
companion object {
|
||||
//站点UUID
|
||||
const val M2_MAP_STATION_MAKER = "m2_map_station_maker"
|
||||
|
||||
/**
|
||||
* Marker类型
|
||||
*/
|
||||
const val TYPE_MARKER_M2_LINE = "TYPE_MARKER_M2_LINE"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.mogo.och.shuttle.passenger.model
|
||||
|
||||
import android.content.Context
|
||||
import com.mogo.och.shuttle.passenger.callback.ADASCallback
|
||||
import com.mogo.och.data.bean.BusStationBean
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2023/2/2
|
||||
*/
|
||||
class PM2ADASModel private constructor() {
|
||||
|
||||
private var mContext: Context? = null
|
||||
private var mAdasCallback: ADASCallback? = null
|
||||
|
||||
companion object {
|
||||
val TAG = PM2ADASModel::class.java.simpleName
|
||||
val INSTANCE: PM2ADASModel by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
|
||||
PM2ADASModel()
|
||||
}
|
||||
}
|
||||
|
||||
fun init(context : Context){
|
||||
this.mContext = context
|
||||
}
|
||||
|
||||
fun setAdasCallback(adasCallback: ADASCallback?){
|
||||
this.mAdasCallback = adasCallback
|
||||
}
|
||||
|
||||
fun updateHDMapStations(stations: MutableList<BusStationBean>){
|
||||
var stationsList = mutableListOf<MutableList<Double>>()
|
||||
for (i in stations.indices){
|
||||
var listLatLng = mutableListOf<Double>() // 0: long 1:lat
|
||||
listLatLng.add(stations[i].lon)
|
||||
listLatLng.add(stations[i].lat)
|
||||
stationsList.add(listLatLng)
|
||||
}
|
||||
mAdasCallback?.updateHDMapStations(stationsList)
|
||||
}
|
||||
|
||||
fun removeHDMapStations(){
|
||||
mAdasCallback?.removeHDMapStations()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,480 @@
|
||||
package com.mogo.och.shuttle.passenger.model
|
||||
|
||||
import android.content.Context
|
||||
import android.media.AudioAttributes
|
||||
import android.media.AudioFocusRequest
|
||||
import android.media.AudioManager
|
||||
import android.net.ConnectivityManager
|
||||
import android.os.Build
|
||||
import android.os.Handler
|
||||
import androidx.annotation.RequiresApi
|
||||
import com.mogo.commons.module.intent.IMogoIntentListener
|
||||
import com.mogo.commons.module.intent.IntentManager
|
||||
import com.mogo.commons.voice.AIAssist
|
||||
import com.mogo.commons.voice.IMogoVoiceCmdCallBack
|
||||
import com.mogo.eagle.core.data.config.FunctionBuildConfig
|
||||
import com.mogo.eagle.core.data.map.MogoLocation
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoAutopilotStatusListener
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoChassisLocationGCJ02Listener
|
||||
import com.mogo.eagle.core.function.api.telematic.IReceivedMsgListener
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
|
||||
import com.mogo.eagle.core.function.call.telematic.CallerTelematicListenerManager
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.Logger
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
|
||||
import com.mogo.eagle.core.utilcode.util.GsonUtils
|
||||
import com.mogo.eagle.core.utilcode.util.NetworkUtils
|
||||
import com.mogo.eagle.core.utilcode.util.StringUtils
|
||||
import com.mogo.eagle.core.utilcode.util.ToastUtils
|
||||
import com.mogo.och.common.module.biz.lansocket.LoginLanPassengerSocket
|
||||
import com.mogo.och.common.module.manager.socket.cloud.OCHSocketMessageManager.pushAppOperationalMsgBox
|
||||
import com.mogo.och.common.module.constant.OchCommonConst
|
||||
import com.mogo.och.common.module.manager.autopilot.autopilot.IOchAutopilotStatusListener
|
||||
import com.mogo.och.common.module.manager.autopilot.autopilot.OchAutoPilotStatusListenerManager
|
||||
import com.mogo.och.common.module.manager.autopilot.location.OchLocationManager
|
||||
import com.mogo.och.common.module.network.OchCommonServiceCallback
|
||||
import com.mogo.och.common.module.manager.distance.IDistanceListener
|
||||
import com.mogo.och.common.module.manager.distance.TrajectoryAndDistanceManager
|
||||
import com.mogo.och.common.module.manager.loop.BizLoopManager
|
||||
import com.mogo.och.common.module.manager.loop.LoopInfo
|
||||
import com.mogo.och.common.module.manager.socket.lan.LanSocketManager
|
||||
import com.mogo.och.common.module.manager.socket.lan.bean.AppConnectMsg
|
||||
import com.mogo.och.common.module.manager.socket.lan.bean.BaseDPMsg
|
||||
import com.mogo.och.common.module.manager.socket.lan.bean.BusinessType
|
||||
import com.mogo.och.common.module.manager.socket.lan.bean.DPMsgType
|
||||
import com.mogo.och.common.module.manager.socket.lan.bean.TaskDetailsMsg
|
||||
import com.mogo.och.common.module.utils.DateTimeUtil
|
||||
import com.mogo.och.common.module.voice.VoiceNotice
|
||||
import com.mogo.och.common.module.voice.VoiceNotice.showNotice
|
||||
import com.mogo.och.data.bean.BusRoutesResult
|
||||
import com.mogo.och.data.bean.BusStationBean
|
||||
import com.mogo.och.data.bean.BusTransferData
|
||||
import com.mogo.och.shuttle.passenger.R
|
||||
import com.mogo.och.shuttle.passenger.bean.response.PassengerOperationStatusResponse
|
||||
import com.mogo.och.shuttle.passenger.bean.response.PassengerRoutesResponse
|
||||
import com.mogo.och.shuttle.passenger.callback.AutoPilotStatusCallback
|
||||
import com.mogo.och.shuttle.passenger.callback.DrivingInfoCallback
|
||||
import com.mogo.och.shuttle.passenger.constant.BusPassengerConst
|
||||
import com.mogo.och.shuttle.passenger.network.PassengerServiceManager
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import kotlin.math.abs
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2023/1/31
|
||||
*/
|
||||
class PM2DrivingModel private constructor() {
|
||||
|
||||
private var mContext: Context? = null
|
||||
|
||||
private var routesResult: BusRoutesResult? = null
|
||||
|
||||
|
||||
var mStations = mutableListOf<BusStationBean>()
|
||||
private var mNextStationIndex = 0 // A-B要到达站的index
|
||||
private var isGoingToNextStation = false //是否前往下一站过程中
|
||||
|
||||
private var mDrivingInfoCallback: DrivingInfoCallback? = null //行程信息
|
||||
private var mAutoStatusCallback: AutoPilotStatusCallback? = null //自动驾驶状态
|
||||
|
||||
private var operationStatus: PassengerOperationStatusResponse.Result? = null
|
||||
|
||||
private val handler = Handler(Handler.Callback { msg ->
|
||||
if (msg.what == MSG_QUERY_BUS_P_STATION) {
|
||||
queryDriverOperationStatus()
|
||||
return@Callback true
|
||||
}
|
||||
false
|
||||
})
|
||||
|
||||
companion object {
|
||||
val TAG = PM2DrivingModel::class.java.simpleName
|
||||
const val MSG_QUERY_BUS_P_STATION = 1001
|
||||
val INSTANCE: PM2DrivingModel by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
|
||||
PM2DrivingModel()
|
||||
}
|
||||
}
|
||||
|
||||
fun init(context: Context) {
|
||||
mContext = context
|
||||
initListener()
|
||||
queryDriverByLocalDriver()
|
||||
queryDriverOperationStatus()
|
||||
BizLoopManager.setLoopFunction(TAG, LoopInfo(2,::queryDriverSiteByCoordinate, scheduler = Schedulers.io()))
|
||||
}
|
||||
|
||||
private fun queryDriverByLocalDriver() {
|
||||
//本地去请求司机端
|
||||
val msg = TaskDetailsMsg("task", BusinessType.shuttle)
|
||||
LanSocketManager.sendMsgToServer(msg)
|
||||
}
|
||||
|
||||
private fun initListener() {
|
||||
//自动驾驶状态监听
|
||||
OchAutoPilotStatusListenerManager.addListener(TAG, mAutoPilotStatusListener)
|
||||
|
||||
// 定位监听
|
||||
OchLocationManager.addGCJ02Listener(TAG, 3, mMapLocationListener)
|
||||
|
||||
//司乘屏通信监听
|
||||
CallerTelematicListenerManager.addListener(TAG, mReceivedMsgListener)
|
||||
|
||||
//网络监听
|
||||
IntentManager.getInstance()
|
||||
.registerIntentListener(ConnectivityManager.CONNECTIVITY_ACTION, mNetWorkIntentListener)
|
||||
|
||||
TrajectoryAndDistanceManager.addDistanceListener(TAG, trajectoryListener)
|
||||
|
||||
}
|
||||
|
||||
fun releaseListener() {
|
||||
//自动驾驶状态监听
|
||||
CallerAutoPilotStatusListenerManager.removeListener(TAG)
|
||||
|
||||
// 定位监听
|
||||
OchLocationManager.removeGCJ02Listener(TAG)
|
||||
|
||||
CallerTelematicListenerManager.removeListener(TAG)
|
||||
|
||||
cleanStation("release")
|
||||
|
||||
TrajectoryAndDistanceManager.removeListener(TAG)
|
||||
|
||||
}
|
||||
|
||||
fun setDrivingInfoCallback(drivingInfoCallback : DrivingInfoCallback?){
|
||||
mDrivingInfoCallback = drivingInfoCallback
|
||||
}
|
||||
|
||||
fun setAutoStatusCallback(autoPilotStatusCallback: AutoPilotStatusCallback?){
|
||||
mAutoStatusCallback = autoPilotStatusCallback
|
||||
}
|
||||
|
||||
private val mNetWorkIntentListener = IMogoIntentListener { intentStr, _ ->
|
||||
if (ConnectivityManager.CONNECTIVITY_ACTION == intentStr) {
|
||||
if (NetworkUtils.isConnected(mContext)) {
|
||||
queryDriverOperationStatus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val mReceivedMsgListener: IReceivedMsgListener =
|
||||
object : IReceivedMsgListener{
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
override fun onReceivedMsg(type: Int, byteArray: ByteArray) {//接收司机端发来的信息
|
||||
if (OchCommonConst.BUSINESS_STRING == type){
|
||||
val baseMsg = GsonUtils.fromJson(String(byteArray), BaseDPMsg::class.java)
|
||||
Logger.d(
|
||||
SceneConstant.M_BUS_P + TAG, "onReceivedMsg = " + GsonUtils.toJson(baseMsg)
|
||||
)
|
||||
|
||||
if (baseMsg != null && baseMsg.type == DPMsgType.TYPE_COMMON.type) {
|
||||
val msg = GsonUtils.fromJson(String(byteArray), AppConnectMsg::class.java)
|
||||
|
||||
if (msg != null && msg.isPlay){ //播报
|
||||
speakTTS(msg.msg)
|
||||
}
|
||||
|
||||
if (msg != null && msg.isViewShow) { //消息盒子显示内容
|
||||
pushAppOperationalMsgBox(
|
||||
DateTimeUtil.getCurrentTimeStamp(),msg.msg)
|
||||
}
|
||||
}else if (baseMsg != null && baseMsg.type == DPMsgType.TYPE_TASK_DETAILS.type) {
|
||||
val msg = GsonUtils.fromJson(String(byteArray), TaskDetailsMsg::class.java)
|
||||
Logger.d(
|
||||
SceneConstant.M_BUS_P + TAG, "onReceivedMsg = " + GsonUtils.toJson(msg)
|
||||
)
|
||||
if (msg == null || msg.msg?.isEmpty() == true) {
|
||||
updateLocalOrder()
|
||||
return
|
||||
}
|
||||
val result = GsonUtils.fromJson(msg.msg, BusTransferData::class.java)
|
||||
mDrivingInfoCallback?.changeOperationStatus(result.loginStatus == 1)
|
||||
if (result != null && result.routesResult == null){
|
||||
updateLocalOrder()
|
||||
}
|
||||
|
||||
if (routesResult == null ||
|
||||
(result != null && result.routesResult?.writeVersion!! > routesResult!!.writeVersion)) {
|
||||
routesResult = result.routesResult
|
||||
updatePassengerRouteInfo(routesResult!!)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val trajectoryListener: IDistanceListener = object : IDistanceListener {
|
||||
override fun distanceCallback(distance: Float) {
|
||||
val lastTime = distance / BusPassengerConst.BUS_AVERAGE_SPEED * 3.6 //秒
|
||||
d(SceneConstant.M_BUS_P + TAG, "轨迹排查==lastSumLength = $distance")
|
||||
if (routesResult != null) {
|
||||
for (site in routesResult!!.sites) {
|
||||
if (site.drivingStatus == BusPassengerConst.STATION_STATUS_STOPPED && !site.isLeaving) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
// 小于200m 播报站点介绍
|
||||
if (distance < 200) {
|
||||
val stationNext = mStations[mNextStationIndex]
|
||||
if (!stationNext.isPlayTts) {
|
||||
if (!StringUtils.isEmpty(stationNext.introduction)) {
|
||||
showNotice(stationNext.introduction)
|
||||
stationNext.isPlayTts = true
|
||||
}
|
||||
}
|
||||
}
|
||||
mDrivingInfoCallback?.updateRemainMT(
|
||||
distance.toLong(),
|
||||
lastTime.toLong()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
private fun speakTTS(msg: String) {
|
||||
|
||||
val mAudioManager = mContext?.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
val mAudioAttributes = AudioAttributes.Builder()
|
||||
.setUsage(AudioAttributes.USAGE_MEDIA) //设置声音的用途
|
||||
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) //设置声音的类型
|
||||
.build()
|
||||
val mAudioFocusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) //设置焦点类型
|
||||
.setAudioAttributes(mAudioAttributes) //设置声音属性
|
||||
.setAcceptsDelayedFocusGain(false) //设置接受延迟获取焦点,需要设置OnAudioFocusChangeListener来监听焦点的获取
|
||||
.build()
|
||||
mAudioManager.requestAudioFocus(mAudioFocusRequest) //抢占焦点
|
||||
|
||||
VoiceNotice.speakTTSVoiceWithLevel(msg,AIAssist.LEVEL0,object : IMogoVoiceCmdCallBack{
|
||||
override fun onSpeakEnd(speakText: String?) {
|
||||
mAudioManager.abandonAudioFocusRequest(mAudioFocusRequest)
|
||||
}
|
||||
|
||||
override fun onSpeakError(speakText: String?, errorMsg: String?) {
|
||||
mAudioManager.abandonAudioFocusRequest(mAudioFocusRequest)
|
||||
}
|
||||
|
||||
override fun onSpeakSelectTimeOut(speakText: String?) {
|
||||
mAudioManager.abandonAudioFocusRequest(mAudioFocusRequest)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private val mMapLocationListener: IMoGoChassisLocationGCJ02Listener =
|
||||
object : IMoGoChassisLocationGCJ02Listener{
|
||||
override fun onChassisLocationGCJ02(mogoLocation: MogoLocation?) {
|
||||
if (null == mogoLocation) return
|
||||
updateSpeed(mogoLocation)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateSpeed(mogoLocation: MogoLocation) {
|
||||
// km/h
|
||||
val speedKM = (abs(mogoLocation.gnssSpeed) * 3.6f).toInt()
|
||||
|
||||
mDrivingInfoCallback?.updateSpeed(speedKM)
|
||||
}
|
||||
|
||||
private val mAutoPilotStatusListener: IOchAutopilotStatusListener =
|
||||
object : IOchAutopilotStatusListener {
|
||||
|
||||
override fun onAutopilotStatusResponse(state: Int) {
|
||||
super.onAutopilotStatusResponse(state)
|
||||
d(SceneConstant.M_BUS_P+TAG, "onAutopilotStatusResponse ===== $state")
|
||||
if (IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING != state){
|
||||
//美化模式下且行程中
|
||||
if (FunctionBuildConfig.isDemoMode &&
|
||||
mNextStationIndex>= 0 && mNextStationIndex <= mStations.size - 1
|
||||
&& isGoingToNextStation){
|
||||
mAutoStatusCallback?.updateAutoStatus(true)
|
||||
}else{//非美化模式下
|
||||
mAutoStatusCallback?.updateAutoStatus(false)
|
||||
}
|
||||
}else{//自驾状态 2
|
||||
mAutoStatusCallback?.updateAutoStatus(true)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun queryDriverOperationDelay() {
|
||||
handler.sendEmptyMessageDelayed(MSG_QUERY_BUS_P_STATION,
|
||||
BusPassengerConst.QUERY_BUS_P_STATION_DELAY
|
||||
)
|
||||
}
|
||||
|
||||
private fun queryDriverOperationStatus() {
|
||||
mContext?.let {
|
||||
PassengerServiceManager.queryDriverOperationStatus(
|
||||
it,
|
||||
object : OchCommonServiceCallback<PassengerOperationStatusResponse> {
|
||||
override fun onSuccess(data: PassengerOperationStatusResponse?) {
|
||||
if (data?.data == null) return
|
||||
if (data.data.driverStatus != operationStatus?.driverStatus
|
||||
|| data.data.plateNumber != operationStatus?.plateNumber){
|
||||
d(SceneConstant.M_BUS_P+TAG, "queryDriverOperationStatus ===== 车牌或者登陆状态有变更")
|
||||
mDrivingInfoCallback?.changeOperationStatus(data.data.driverStatus == 1)
|
||||
}
|
||||
operationStatus = data.data as PassengerOperationStatusResponse.Result
|
||||
}
|
||||
|
||||
override fun onError() {
|
||||
if (!NetworkUtils.isConnected(mContext)) {
|
||||
ToastUtils.showShort(mContext!!.getString(R.string.network_error_tip))
|
||||
} else {
|
||||
ToastUtils.showShort(mContext!!.getString(R.string.request_error_tip))
|
||||
}
|
||||
queryDriverByLocalDriver()
|
||||
}
|
||||
|
||||
override fun onFail(code: Int, msg: String) {
|
||||
//延迟3s再次查询
|
||||
queryDriverOperationDelay()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fun queryDriverSiteByCoordinate(){
|
||||
mContext?.let {
|
||||
PassengerServiceManager.queryDriverSiteByCoordinate(it,
|
||||
object : OchCommonServiceCallback<PassengerRoutesResponse> {
|
||||
override fun onSuccess(data: PassengerRoutesResponse?) {
|
||||
|
||||
if (data == null || data.result == null){
|
||||
if (routesResult != null) {
|
||||
routesResult = null
|
||||
updateLocalOrder()
|
||||
d(SceneConstant.M_BUS_P+TAG, "queryDriverSiteByCoordinate= result is null")
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
if (data.result != null && data.result.equals(routesResult)){
|
||||
d(SceneConstant.M_BUS_P+TAG, "queryDriverSiteByCoordinate= not update")
|
||||
return
|
||||
}
|
||||
|
||||
if (routesResult != null &&
|
||||
routesResult!!.writeVersion < data.result.writeVersion
|
||||
) {
|
||||
routesResult = data.result
|
||||
}
|
||||
|
||||
if (routesResult == null) {
|
||||
routesResult = data.result
|
||||
}
|
||||
updatePassengerRouteInfo(data.result)
|
||||
}
|
||||
|
||||
override fun onError() {
|
||||
CallerLogger.d(
|
||||
SceneConstant.Companion.M_BUS_P + TAG,
|
||||
"queryDriverSiteByCoordinate = onError ="
|
||||
+ ", sn = " + LoginLanPassengerSocket.driverSn
|
||||
)
|
||||
queryDriverByLocalDriver()
|
||||
}
|
||||
|
||||
override fun onFail(code: Int, msg: String?) {
|
||||
d(SceneConstant.M_BUS_P+TAG, "queryDriverSiteByCoordinate = %s", msg)
|
||||
if (code == 1003){
|
||||
queryDriverOperationDelay()
|
||||
cleanStation("queryDriverSiteByCoordinate 1003")
|
||||
}
|
||||
if (LoginLanPassengerSocket.driverSn.isEmpty()){
|
||||
return
|
||||
}
|
||||
if (code == 1003) {
|
||||
routesResult = null
|
||||
isGoingToNextStation = false
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateLocalOrder(){
|
||||
routesResult = null
|
||||
mNextStationIndex = 0
|
||||
cleanStation("queryDriverSiteByCoordinate")
|
||||
isGoingToNextStation = false
|
||||
mDrivingInfoCallback?.showNoTaskView(true)
|
||||
}
|
||||
|
||||
private fun updatePassengerRouteInfo(result: BusRoutesResult) {
|
||||
|
||||
if (result == null) {
|
||||
updateLocalOrder()
|
||||
return
|
||||
}
|
||||
|
||||
if (routesResult != null && routesResult!!.lineId != result.lineId){
|
||||
d(SceneConstant.M_BUS_P+TAG, "lineId change= clearCustomPolyline")
|
||||
mDrivingInfoCallback?.clearCustomPolyline()
|
||||
}
|
||||
|
||||
d(SceneConstant.M_BUS_P+TAG, "queryDriverSiteByCoordinate= update")
|
||||
routesResult = result
|
||||
|
||||
mDrivingInfoCallback?.updateLine(result.name, result.runningDur)
|
||||
if (result.sites != null) {
|
||||
mDrivingInfoCallback?.showNoTaskView(false)
|
||||
val stations: List<BusStationBean> = result.sites
|
||||
mStations.clear()
|
||||
mStations.addAll(stations)
|
||||
mDrivingInfoCallback?.updateLineStations(mStations)
|
||||
for (i in stations.indices) {
|
||||
val station: BusStationBean = stations[i]
|
||||
if (station.drivingStatus == BusPassengerConst.STATION_STATUS_STOPPED
|
||||
&& station.isLeaving && i + 1 < stations.size) {
|
||||
mDrivingInfoCallback?.updateStationsInfo(stations as MutableList<BusStationBean>, i + 1, false)
|
||||
d(SceneConstant.M_BUS_P+TAG,"och-rotting--mNextStationIndex = $mNextStationIndex , i = $i")
|
||||
d(SceneConstant.M_BUS_P+TAG,"och-rotting--start ")
|
||||
isGoingToNextStation = true
|
||||
mNextStationIndex = i + 1
|
||||
val startStation = mStations[i]
|
||||
val endStation = mStations[i + 1]
|
||||
setTrajectoryStation(startStation, endStation, result.lineId)
|
||||
return
|
||||
} else if (station.drivingStatus == BusPassengerConst.STATION_STATUS_STOPPED && !station.isLeaving) {
|
||||
d(SceneConstant.M_BUS_P+TAG,"och-rotting--mNextStationIndex = $mNextStationIndex , i = $i")
|
||||
d(SceneConstant.M_BUS_P+TAG,"och-rotting--arrived ")
|
||||
if (i == stations.size - 1) {
|
||||
cleanStation("updatePassengerRouteInfo最后一个站点")
|
||||
}
|
||||
isGoingToNextStation = false
|
||||
mDrivingInfoCallback?.updateStationsInfo(stations as MutableList<BusStationBean>, i, true)
|
||||
return
|
||||
}else{
|
||||
// d(SceneConstant.M_BUS_P+TAG,"och-rotting--BusStationBean = " + GsonUtils.toJson(station))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun setTrajectoryStation(
|
||||
startStationInfo: BusStationBean,
|
||||
endStationInfo: BusStationBean,
|
||||
lineId: Int
|
||||
) {
|
||||
val startStation = MogoLocation()
|
||||
startStation.longitude = startStationInfo.gcjLon
|
||||
startStation.latitude = startStationInfo.gcjLat
|
||||
val endStation = MogoLocation()
|
||||
endStation.longitude = endStationInfo.gcjLon
|
||||
endStation.latitude = endStationInfo.gcjLat
|
||||
TrajectoryAndDistanceManager.setStationPoint(startStation, endStation, lineId.toLong())
|
||||
}
|
||||
|
||||
private fun cleanStation(type: String) {
|
||||
d(SceneConstant.M_BUS_P + TAG, "清理站点:$type")
|
||||
TrajectoryAndDistanceManager.setStationPoint(null, null, -1L)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.mogo.och.shuttle.passenger.presenter
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.mogo.commons.mvp.Presenter
|
||||
import com.mogo.och.shuttle.passenger.callback.ADASCallback
|
||||
import com.mogo.och.shuttle.passenger.constant.M2Const.Companion.M2_MAP_STATION_MAKER
|
||||
import com.mogo.och.shuttle.passenger.model.PM2ADASModel
|
||||
import com.mogo.och.shuttle.passenger.ui.PM2HPMapFragment
|
||||
|
||||
class PM2ADASPresenter(view: PM2HPMapFragment?) :
|
||||
Presenter<PM2HPMapFragment?>(view), ADASCallback {
|
||||
|
||||
init {
|
||||
PM2ADASModel.INSTANCE.init(context)
|
||||
initListener()
|
||||
}
|
||||
|
||||
private fun initListener() {
|
||||
PM2ADASModel.INSTANCE.setAdasCallback(this)
|
||||
}
|
||||
|
||||
private fun removeListener() {
|
||||
PM2ADASModel.INSTANCE.setAdasCallback(null)
|
||||
}
|
||||
|
||||
override fun onDestroy(owner: LifecycleOwner) {
|
||||
super.onDestroy(owner)
|
||||
removeListener()
|
||||
}
|
||||
|
||||
override fun updateHDMapStations(stations: MutableList<MutableList<Double>>) {
|
||||
for (i in stations.indices){
|
||||
mView?.setMapMaker(M2_MAP_STATION_MAKER+i,stations[i])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun removeHDMapStations() {
|
||||
mView?.removeMapMaker(M2_MAP_STATION_MAKER)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package com.mogo.och.shuttle.passenger.presenter
|
||||
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.amap.api.maps.model.LatLng
|
||||
import com.mogo.commons.mvp.Presenter
|
||||
import com.mogo.eagle.core.utilcode.util.ThreadUtils
|
||||
import com.mogo.och.shuttle.passenger.callback.AutoPilotStatusCallback
|
||||
import com.mogo.och.shuttle.passenger.callback.DrivingInfoCallback
|
||||
import com.mogo.och.shuttle.passenger.model.PM2ADASModel
|
||||
import com.mogo.och.shuttle.passenger.model.PM2DrivingModel
|
||||
import com.mogo.och.shuttle.passenger.ui.PM2DrivingInfoFragment
|
||||
import com.mogo.och.data.bean.BusStationBean
|
||||
|
||||
class PM2DrivingPresenter(view: PM2DrivingInfoFragment?) :
|
||||
Presenter<PM2DrivingInfoFragment?>(view), DrivingInfoCallback, AutoPilotStatusCallback {
|
||||
|
||||
init {
|
||||
PM2DrivingModel.INSTANCE.init(context)
|
||||
PM2ADASModel.INSTANCE.init(context)
|
||||
initListener()
|
||||
}
|
||||
|
||||
override fun onDestroy(owner: LifecycleOwner) {
|
||||
super.onDestroy(owner)
|
||||
destroyListener()
|
||||
PM2DrivingModel.INSTANCE.releaseListener()
|
||||
}
|
||||
|
||||
private fun initListener(){
|
||||
PM2DrivingModel.INSTANCE.setDrivingInfoCallback(this)
|
||||
PM2DrivingModel.INSTANCE.setAutoStatusCallback(this)
|
||||
}
|
||||
|
||||
private fun destroyListener(){
|
||||
PM2DrivingModel.INSTANCE.setDrivingInfoCallback(null)
|
||||
PM2DrivingModel.INSTANCE.setAutoStatusCallback(null)
|
||||
}
|
||||
|
||||
override fun updateSpeed(speed: Int) {
|
||||
// CallerLogger.d(
|
||||
// SceneConstant.M_BUS_P + "speed = ",speed.toString()
|
||||
// )
|
||||
ThreadUtils.runOnUiThread {
|
||||
mView?.updateSpeed(speed)
|
||||
}
|
||||
}
|
||||
|
||||
override fun updatePlateNumber(carNum: String) {
|
||||
ThreadUtils.runOnUiThread {
|
||||
mView?.updateCarPlateNum(carNum)
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateLine(lineName: String, lineDuring: String) {
|
||||
ThreadUtils.runOnUiThread {
|
||||
mView?.updateTaskName(lineName)
|
||||
mView?.updateTaskDuringTime(lineDuring)
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateRemainMT(meters: Long, timeInSecond: Long) {
|
||||
ThreadUtils.runOnUiThread {
|
||||
mView?.updateRemainMT(meters, timeInSecond) //米,秒
|
||||
}
|
||||
}
|
||||
|
||||
override fun changeOperationStatus(loginStatus: Boolean) {
|
||||
ThreadUtils.runOnUiThread {
|
||||
mView?.changeOperationStatus(loginStatus)
|
||||
}
|
||||
}
|
||||
|
||||
override fun showNoTaskView(isTrue: Boolean) {
|
||||
ThreadUtils.runOnUiThread {
|
||||
mView?.showNoTaskView(!isTrue)
|
||||
}
|
||||
if (isTrue){
|
||||
PM2ADASModel.INSTANCE.removeHDMapStations()
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateLineStations(stations: MutableList<BusStationBean>) {
|
||||
|
||||
val stationsList = mutableListOf<LatLng>()
|
||||
val stationsListPass = mutableListOf<LatLng>()
|
||||
var startStation: LatLng? = null
|
||||
var endStation: LatLng? = null
|
||||
|
||||
for (i in stations.indices){
|
||||
val station = stations[i]
|
||||
val latLng = LatLng(station.gcjLat,station.gcjLon)
|
||||
if(i==0){
|
||||
startStation = latLng
|
||||
continue
|
||||
}
|
||||
if(i==stations.size-1){
|
||||
endStation = latLng
|
||||
continue
|
||||
}
|
||||
if(station.drivingStatus==1){//行驶信息,0初始值;1已经过;2当前站;3未到站
|
||||
stationsListPass.add(latLng)
|
||||
}else if(station.drivingStatus==2){
|
||||
if(station.isLeaving){
|
||||
stationsListPass.add(latLng)
|
||||
}else{
|
||||
stationsList.add(latLng)
|
||||
}
|
||||
}else{
|
||||
stationsList.add(latLng)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ThreadUtils.runOnUiThread {
|
||||
mView?.updateLineStations(stationsList,stationsListPass,startStation,endStation)
|
||||
}
|
||||
PM2ADASModel.INSTANCE.updateHDMapStations(stations)
|
||||
}
|
||||
|
||||
override fun updateStationsInfo(stations: MutableList<BusStationBean>, i: Int, isArrived: Boolean) {
|
||||
ThreadUtils.runOnUiThread {
|
||||
mView?.updateStationsInfo(stations,i,isArrived)
|
||||
}
|
||||
}
|
||||
|
||||
override fun clearCustomPolyline() {
|
||||
ThreadUtils.runOnUiThread {
|
||||
mView?.clearCustomPolyline()
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateAutoStatus(isOpen: Boolean) {
|
||||
ThreadUtils.runOnUiThread {
|
||||
mView?.updateAutoStatus(isOpen)
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateAutoStatus(status: Int) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.mogo.och.shuttle.passenger.presenter
|
||||
|
||||
import com.mogo.commons.mvp.Presenter
|
||||
import com.mogo.och.shuttle.passenger.ui.PM2BaseFragment
|
||||
|
||||
class PM2Presenter(view: PM2BaseFragment?) :
|
||||
Presenter<PM2BaseFragment?>(view)
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.mogo.och.shuttle.passenger.ui
|
||||
|
||||
import com.mogo.commons.mvp.MvpFragment
|
||||
import com.mogo.eagle.core.utilcode.util.AppUtils
|
||||
import com.mogo.och.shuttle.passenger.R
|
||||
import com.mogo.och.shuttle.passenger.presenter.PM2Presenter
|
||||
import com.mogo.och.common.module.wigets.media.MediaPlayerFragment
|
||||
import kotlinx.android.synthetic.main.shuttle_p_m2_fragment.tv_shuttle_b2_p_version
|
||||
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2022/4/12
|
||||
*/
|
||||
class PM2BaseFragment :
|
||||
MvpFragment<PM2BaseFragment?, PM2Presenter?>() {
|
||||
|
||||
private var drivingFragment : PM2DrivingInfoFragment? = null
|
||||
private var hdMapFragment : PM2HPMapFragment? = null
|
||||
private var mediaFragment : MediaPlayerFragment? = null
|
||||
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.shuttle_p_m2_fragment
|
||||
}
|
||||
|
||||
override fun getTagName(): String {
|
||||
return TAG
|
||||
}
|
||||
|
||||
override fun initViews() {
|
||||
//横竖屏
|
||||
// setScreenDirection()
|
||||
tv_shuttle_b2_p_version.text = "版本:${AppUtils.getAppVersionName()}"
|
||||
//隐藏小地图
|
||||
initFragment()
|
||||
}
|
||||
|
||||
// private fun setScreenDirection() {
|
||||
// var ro = Settings.System.getInt(context?.contentResolver,
|
||||
// Settings.System.USER_ROTATION,Surface.ROTATION_270)
|
||||
// if (ro != Surface.ROTATION_270){
|
||||
// ro = Surface.ROTATION_270
|
||||
// }
|
||||
// Settings.System.putInt(context?.contentResolver,
|
||||
// Settings.System.USER_ROTATION,ro)
|
||||
// }
|
||||
|
||||
/**
|
||||
* 初始化行程信息,高静地图,宣传 三个fragment
|
||||
*/
|
||||
private fun initFragment() {
|
||||
|
||||
if (drivingFragment == null) drivingFragment = PM2DrivingInfoFragment()
|
||||
childFragmentManager.beginTransaction().add(R.id.driving_fragment, drivingFragment!!)
|
||||
.show(drivingFragment!!).commitAllowingStateLoss()
|
||||
|
||||
if (hdMapFragment == null) hdMapFragment = PM2HPMapFragment()
|
||||
childFragmentManager.beginTransaction().add(R.id.hd_map_fragment, hdMapFragment!!)
|
||||
.show(hdMapFragment!!).commitAllowingStateLoss()
|
||||
|
||||
if (mediaFragment == null) mediaFragment = MediaPlayerFragment()
|
||||
childFragmentManager.beginTransaction().add(R.id.video_fragment, mediaFragment!!)
|
||||
.show(mediaFragment!!).commitAllowingStateLoss()
|
||||
}
|
||||
|
||||
override fun createPresenter(): PM2Presenter {
|
||||
return PM2Presenter(this)
|
||||
}
|
||||
|
||||
companion object {
|
||||
public val TAG = PM2BaseFragment::class.java.simpleName
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,301 @@
|
||||
package com.mogo.och.shuttle.passenger.ui
|
||||
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.drawable.AnimationDrawable
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.amap.api.maps.model.LatLng
|
||||
import com.mogo.commons.AbsMogoApplication
|
||||
import com.mogo.commons.mvp.MvpFragment
|
||||
import com.mogo.eagle.core.function.hmi.ui.setting.ToggleDebugView
|
||||
import com.mogo.eagle.core.function.view.SiteMarkerBean
|
||||
import com.mogo.eagle.core.widget.media.video.TextureVideoViewOutlineProvider
|
||||
import com.mogo.och.shuttle.passenger.R
|
||||
import com.mogo.och.shuttle.passenger.presenter.PM2DrivingPresenter
|
||||
import com.mogo.och.common.module.utils.DateTimeUtil.*
|
||||
import com.mogo.och.common.module.utils.NumberFormatUtil
|
||||
import com.mogo.och.data.bean.BusStationBean
|
||||
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.auto_tv
|
||||
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.clg_distance_left_time
|
||||
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.group_not_select_line
|
||||
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.group_stationinfo
|
||||
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.iv_animal_list
|
||||
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.line_during_tv
|
||||
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.line_name_tv
|
||||
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.overMapView
|
||||
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.speed_tv
|
||||
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.station_name_tv
|
||||
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.tv_arrived_notice
|
||||
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.tv_distance
|
||||
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.tv_left_time
|
||||
import kotlinx.android.synthetic.main.shuttle_p_m2_driving_info_fragment.tv_next_station_title
|
||||
|
||||
import me.jessyan.autosize.utils.AutoSizeUtils
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2022/4/12
|
||||
*/
|
||||
class PM2DrivingInfoFragment :
|
||||
MvpFragment<PM2DrivingInfoFragment?, PM2DrivingPresenter?>() {
|
||||
|
||||
val stationIcon = BitmapFactory.decodeResource(AbsMogoApplication.getApp().resources, R.drawable.shuttle_p_m2_map_staton_icon)
|
||||
val stationPassIcon = BitmapFactory.decodeResource(AbsMogoApplication.getApp().resources, R.drawable.shuttle_p_m2_map_staton_arrived_icon)
|
||||
val startStationIcon = BitmapFactory.decodeResource(AbsMogoApplication.getApp().resources, R.drawable.shuttle_p_m2_map_start_icon)
|
||||
val endStationIcon = BitmapFactory.decodeResource(AbsMogoApplication.getApp().resources, R.drawable.shuttle_p_m2_map_end_icon)
|
||||
|
||||
/**
|
||||
* 改变自动驾驶状态
|
||||
*
|
||||
* @param status 2 - running 1 - enable 2 - disable
|
||||
*/
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.shuttle_p_m2_driving_info_fragment
|
||||
}
|
||||
|
||||
override fun getTagName(): String {
|
||||
return TAG
|
||||
}
|
||||
|
||||
override fun initViews() {
|
||||
speed_tv.setOnLongClickListener {
|
||||
context?.let { ToggleDebugView.toggleDebugView.toggle(it) }
|
||||
true
|
||||
}
|
||||
|
||||
line_name_tv.setTextColor(resources.getColor(R.color.shuttle_p_m2_line_name_tv_color))
|
||||
station_name_tv.setTextColor(resources.getColor(R.color.shuttle_p_m2_line_name_tv_color))
|
||||
speed_tv.setVertrial(true)
|
||||
val intArrayOf = intArrayOf(
|
||||
requireContext().resources.getColor(R.color.shuttle_p_m2_color_43cefe),
|
||||
requireContext().resources.getColor(R.color.shuttle_p_m2_color_1466fb)
|
||||
)
|
||||
speed_tv.setmColorList(intArrayOf)
|
||||
|
||||
// current_time_tv.onClick {
|
||||
|
||||
// //测试V2X消息
|
||||
// CallerMsgBoxManager.saveMsgBox(
|
||||
// MsgBoxBean(
|
||||
// MsgBoxType.V2X,
|
||||
// V2XMsg(
|
||||
// "6666",
|
||||
// "超速行驶",
|
||||
// ""
|
||||
// )
|
||||
// )
|
||||
// )
|
||||
//
|
||||
// val noticeTrafficStylePushData = NoticeTrafficStylePushData()
|
||||
// noticeTrafficStylePushData.content= "测试公告布局"
|
||||
// val noticeFromCloudMsg = NoticeFrCloudMsg(null, noticeTrafficStylePushData, 1)
|
||||
// CallerMsgBoxManager.saveMsgBox(
|
||||
// MsgBoxBean(
|
||||
// MsgBoxType.NOTICE, noticeFromCloudMsg)
|
||||
// )
|
||||
// BPRouteDataTestUtils.converToRouteData()
|
||||
// }
|
||||
}
|
||||
|
||||
override fun initViews(savedInstanceState: Bundle?) {
|
||||
super.initViews(savedInstanceState)
|
||||
overMapView?.let {
|
||||
it.onCreateView(savedInstanceState)
|
||||
val radius = AutoSizeUtils.dp2px(requireContext(), 16f)
|
||||
it.outlineProvider = TextureVideoViewOutlineProvider(radius.toFloat())
|
||||
it.clipToOutline = true
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
overMapView?.let{
|
||||
it.onResume()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
overMapView?.let{
|
||||
it.onPause()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
overMapView?.onDestroy()
|
||||
if (mPresenter != null) {
|
||||
mPresenter?.onDestroy(this)
|
||||
}
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
fun updateSpeed(speed: Int){
|
||||
speed_tv.text = speed.toString()
|
||||
}
|
||||
|
||||
fun updateCarPlateNum(plateNum : String){
|
||||
|
||||
}
|
||||
|
||||
fun updateTaskName(name: String){
|
||||
line_name_tv.text = name
|
||||
}
|
||||
|
||||
fun updateTaskDuringTime(time : String){
|
||||
line_during_tv.text = time
|
||||
}
|
||||
|
||||
fun changeOperationStatus(status:Boolean){
|
||||
if (!status){
|
||||
updateNoOrderUI()
|
||||
}
|
||||
}
|
||||
|
||||
fun showNoTaskView(haveTask: Boolean){
|
||||
setLineInfoView(haveTask)
|
||||
}
|
||||
|
||||
private fun setLineInfoView(isShow: Boolean){
|
||||
if (!isShow){
|
||||
updateNoOrderUI()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateNoOrderUI() {
|
||||
line_name_tv.text = resources.getString(R.string.shuttle_p_m2_not_select_line_content)
|
||||
updateNoStationView()
|
||||
overMapView?.let {
|
||||
it.clearSiteMarkers()
|
||||
}
|
||||
clearCustomPolyline()
|
||||
}
|
||||
|
||||
fun clearCustomPolyline(){
|
||||
overMapView?.let {
|
||||
it.clearCustomPolyline()
|
||||
}
|
||||
}
|
||||
private fun updateNoStationView(){
|
||||
station_name_tv.setTextColor(resources.getColor(R.color.shuttle_p_m2_next_tv_color))
|
||||
station_name_tv.text = resources.getString(R.string.shuttle_p_m2_empty_tv)
|
||||
tv_distance.text = resources.getString(R.string.shuttle_p_m2_empty_remain_km)
|
||||
tv_left_time.text = resources.getString(R.string.shuttle_p_m2_empty_remain_minute)
|
||||
noLineShow()
|
||||
}
|
||||
|
||||
override fun createPresenter(): PM2DrivingPresenter {
|
||||
return PM2DrivingPresenter(this)
|
||||
}
|
||||
|
||||
fun updateAutoStatus(isAutoPilot: Boolean) {
|
||||
if (isAutoPilot){
|
||||
context?.let { auto_tv.setTextColor(ContextCompat.getColor(it,R.color.shuttle_p_m2_white_color)) }
|
||||
context?.let { auto_tv.background = ContextCompat.getDrawable(it,R.drawable.shuttle_p_m2_auto_button_bg) }
|
||||
}else{
|
||||
context?.let { auto_tv.setTextColor(ContextCompat.getColor(it,R.color.shuttle_p_m2_color_7094ad)) }
|
||||
context?.let { auto_tv.background = ContextCompat.getDrawable(it,R.drawable.shuttle_p_m2_bg_p_m2_auto) }
|
||||
}
|
||||
}
|
||||
|
||||
fun updateLineStations(
|
||||
stations: MutableList<LatLng>,
|
||||
stationsPass: MutableList<LatLng>,
|
||||
startStation: LatLng?,
|
||||
endStation: LatLng?
|
||||
){
|
||||
overMapView?.let {
|
||||
val stationsList: MutableList<SiteMarkerBean> = mutableListOf()
|
||||
startStation?.let { start->
|
||||
stationsList.add(SiteMarkerBean(start,startStationIcon,0.5f,0.5f))
|
||||
}
|
||||
for (stationsPass in stationsPass) {
|
||||
stationsList.add(SiteMarkerBean(stationsPass,stationPassIcon,0.5f,0.5f))
|
||||
}
|
||||
for (stationsPass in stations) {
|
||||
stationsList.add(SiteMarkerBean(stationsPass,stationIcon,0.5f,0.5f))
|
||||
}
|
||||
endStation?.let {end->
|
||||
stationsList.add(SiteMarkerBean(end,endStationIcon,0.5f,0.5f))
|
||||
}
|
||||
it.drawSiteMarkers(stationsList)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateStationsInfo(stations: MutableList<BusStationBean>, i: Int, isArrived: Boolean){
|
||||
if (stations.size == 0) return
|
||||
if (0<= i && i<stations.size){
|
||||
station_name_tv.setTextColor(resources.getColor(R.color.shuttle_p_m2_next_tv_color))
|
||||
station_name_tv.text = stations[i].name
|
||||
}
|
||||
if (isArrived){//到站
|
||||
tv_distance.text = resources.getString(R.string.shuttle_p_m2_empty_remain_km)
|
||||
tv_left_time.text = resources.getString(R.string.shuttle_p_m2_empty_remain_minute)
|
||||
tv_next_station_title.text = resources.getString(R.string.shuttle_p_m2_station_title_arrived_tv)
|
||||
haveLineAndArrivedStation()
|
||||
}else{ //前往目的地中
|
||||
tv_next_station_title.text = resources.getString(R.string.shuttle_p_m2_next_station_title)
|
||||
haveLineAndArriveingStation()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 剩余里程和时间
|
||||
*/
|
||||
fun updateRemainMT(meters: Long, timeInSecond: Long) { //米。秒
|
||||
var disUnit = "公里"
|
||||
var remainDis: String? = "0"
|
||||
|
||||
if (meters > 0) {
|
||||
if (meters / 1000 < 1) {
|
||||
disUnit = "米"
|
||||
remainDis = meters.toFloat().roundToInt().toString()
|
||||
} else {
|
||||
disUnit = "公里"
|
||||
remainDis = NumberFormatUtil.formatLong(meters.toDouble() / 1000)
|
||||
}
|
||||
}
|
||||
|
||||
val time = ceil(timeInSecond / 60f).toInt()
|
||||
|
||||
"$remainDis$disUnit".also { tv_distance.text = it }
|
||||
"${time}分钟".also { tv_left_time.text = it }
|
||||
}
|
||||
|
||||
fun noLineShow(){
|
||||
// 没有线路展示
|
||||
group_not_select_line.visibility = View.VISIBLE
|
||||
// 下一个站点
|
||||
group_stationinfo.visibility = View.GONE
|
||||
// 距离和剩余大概时间
|
||||
clg_distance_left_time.visibility = View.GONE
|
||||
// 到达站点
|
||||
tv_arrived_notice.visibility = View.GONE
|
||||
|
||||
iv_animal_list.visibility = View.GONE
|
||||
}
|
||||
// 有线路正在到站点
|
||||
fun haveLineAndArriveingStation(){
|
||||
group_not_select_line.visibility = View.GONE
|
||||
group_stationinfo.visibility = View.VISIBLE
|
||||
clg_distance_left_time.visibility = View.VISIBLE
|
||||
tv_arrived_notice.visibility = View.GONE
|
||||
iv_animal_list.visibility = View.GONE
|
||||
}
|
||||
// 有线路到达站点
|
||||
private fun haveLineAndArrivedStation(){
|
||||
group_not_select_line.visibility = View.GONE
|
||||
group_stationinfo.visibility = View.VISIBLE
|
||||
clg_distance_left_time.visibility = View.GONE
|
||||
tv_arrived_notice.visibility = View.VISIBLE
|
||||
iv_animal_list.visibility = View.VISIBLE
|
||||
val animationDrawable = iv_animal_list.drawable as AnimationDrawable
|
||||
animationDrawable.start()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = PM2DrivingInfoFragment::class.java.simpleName
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package com.mogo.och.shuttle.passenger.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import com.mogo.commons.mvp.MvpFragment
|
||||
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d
|
||||
import com.mogo.map.overlay.core.Level
|
||||
import com.mogo.map.overlay.point.Point
|
||||
import com.mogo.map.MapDataWrapper
|
||||
import com.mogo.och.shuttle.passenger.R
|
||||
import com.mogo.och.shuttle.passenger.constant.M2Const.Companion.TYPE_MARKER_M2_LINE
|
||||
import com.mogo.och.shuttle.passenger.presenter.PM2ADASPresenter
|
||||
import com.mogo.och.common.module.utils.OCHThreadPoolManager
|
||||
import kotlinx.android.synthetic.main.shuttle_p_m2_hpmap_fragment.mapBizView
|
||||
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2022/4/12
|
||||
*/
|
||||
class PM2HPMapFragment :
|
||||
MvpFragment<PM2HPMapFragment?, PM2ADASPresenter?>() {
|
||||
/**
|
||||
* 改变自动驾驶状态
|
||||
*
|
||||
* @param status 2 - running 1 - enable 2 - disable
|
||||
*/
|
||||
override fun getLayoutId(): Int {
|
||||
return R.layout.shuttle_p_m2_hpmap_fragment
|
||||
}
|
||||
|
||||
override fun getTagName(): String {
|
||||
return TAG
|
||||
}
|
||||
|
||||
override fun initViews() {
|
||||
}
|
||||
|
||||
override fun initViews(savedInstanceState: Bundle?) {
|
||||
super.initViews(savedInstanceState)
|
||||
mapBizView.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapBizView.onResume()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapBizView.onLowMemory()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
mapBizView.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapBizView.onPause()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
mapBizView.onDestroy()
|
||||
CallerMapUIServiceManager.getOverlayManager()?.let {
|
||||
it.removeAllLines()
|
||||
it.removeAllPoints()
|
||||
}
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun createPresenter(): PM2ADASPresenter {
|
||||
return PM2ADASPresenter(this)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = PM2HPMapFragment::class.java.simpleName
|
||||
}
|
||||
|
||||
fun setMapMaker(
|
||||
uuid: String,
|
||||
station: MutableList<Double>,
|
||||
) {
|
||||
//开启线程执行起终点marker设置
|
||||
val setMapMarkerRunnable = Runnable {
|
||||
d(
|
||||
"setMapMaker= " + Thread.currentThread().name,
|
||||
uuid + "=latitude=" + station[1] + ",longitude=" + station[0]
|
||||
)
|
||||
|
||||
val builder = Point.Options.Builder(
|
||||
TYPE_MARKER_M2_LINE,
|
||||
Level.MAP_MARKER
|
||||
)
|
||||
.setId(uuid)
|
||||
.anchor(0.5f, 0.5f)
|
||||
.set3DMode(true)
|
||||
.isUseGps(true)
|
||||
.controlAngle(true)
|
||||
.icon3DRes(R.raw.star_marker)
|
||||
.longitude(station[0])
|
||||
.latitude(station[1])
|
||||
MapDataWrapper.getCenterLineInfo(
|
||||
station[0], station[1], -1f
|
||||
) {
|
||||
// 有可能鹰眼map为空没有角度。判空使用后可能造成maker角度跟道路角度不一致 地图未初始化会返回空
|
||||
it?.let{
|
||||
builder.rotate(it.angle.toFloat())
|
||||
}
|
||||
val overlayManager = CallerMapUIServiceManager.getOverlayManager()
|
||||
overlayManager?.showOrUpdatePoint(builder.build())
|
||||
}
|
||||
|
||||
}
|
||||
OCHThreadPoolManager.getsInstance().execute(setMapMarkerRunnable)
|
||||
}
|
||||
|
||||
fun removeMapMaker(
|
||||
uuid: String,
|
||||
) {
|
||||
//开启线程移除起终点marker设置
|
||||
val removeMapMarkerRunnable = Runnable {
|
||||
d("RemoveMapMaker=" + Thread.currentThread().name, uuid)
|
||||
val overlayManager = CallerMapUIServiceManager.getOverlayManager()
|
||||
overlayManager?.removeAllPointsInOwner(TYPE_MARKER_M2_LINE)
|
||||
}
|
||||
OCHThreadPoolManager.getsInstance().execute(removeMapMarkerRunnable)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.mogo.och.shuttle.passenger.ui.widget
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import com.mogo.eagle.core.function.api.devatools.IMoGoDevaToolsListener
|
||||
import com.mogo.eagle.core.function.hmi.ui.widget.BlueToothView
|
||||
import com.mogo.eagle.core.utilcode.util.ThreadUtils
|
||||
import com.mogo.och.shuttle.passenger.R
|
||||
import kotlinx.android.synthetic.main.shuttle_p_m2_view_blue_tooth.view.blueView
|
||||
|
||||
/**
|
||||
* 魔戒蓝牙控件
|
||||
* 放置于StatusBar右侧位置
|
||||
*/
|
||||
class M2BlueToothView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : BlueToothView(context, attrs, defStyleAttr),IMoGoDevaToolsListener {
|
||||
|
||||
init {
|
||||
LayoutInflater.from(context).inflate(R.layout.shuttle_p_m2_view_blue_tooth, this, true)
|
||||
}
|
||||
|
||||
override fun mofangStatus(status: Boolean) {
|
||||
ThreadUtils.runOnUiThread {
|
||||
if (status) {
|
||||
blueView.setImageResource(R.drawable.shuttle_p_m2_blue_tooth_close)
|
||||
} else {
|
||||
blueView.setImageResource(R.drawable.shuttle_p_m2_blue_tooth_open)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
package com.mogo.och.shuttle.passenger.ui.widget
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.LinearLayout
|
||||
import com.mogo.eagle.core.data.enums.DataSourceType
|
||||
import com.mogo.eagle.core.data.enums.TrafficLightEnum
|
||||
import com.mogo.eagle.core.function.api.datacenter.union.IMoGoTrafficLightListener
|
||||
import com.mogo.eagle.core.function.call.v2x.CallerTrafficLightListenerManager
|
||||
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
|
||||
import com.mogo.och.shuttle.passenger.R
|
||||
import kotlinx.android.synthetic.main.shuttle_p_m2_traffic_light_view.view.m2_p_traffic_light_bg
|
||||
import kotlinx.android.synthetic.main.shuttle_p_m2_traffic_light_view.view.m2_p_traffic_light_iv
|
||||
import kotlinx.android.synthetic.main.shuttle_p_m2_traffic_light_view.view.m2_p_traffic_light_time_tv
|
||||
|
||||
/**
|
||||
* bus乘客端:红绿灯view
|
||||
*
|
||||
* Created on 2022/3/14
|
||||
*/
|
||||
class M2PTrafficLightView @JvmOverloads constructor(
|
||||
context: Context?,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : LinearLayout(context, attrs, defStyleAttr), IMoGoTrafficLightListener {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "M2PTrafficLightView"
|
||||
}
|
||||
|
||||
private var mCurrentLightId = TrafficLightEnum.BLACK
|
||||
|
||||
init {
|
||||
init(context)
|
||||
}
|
||||
|
||||
private fun init(context: Context?) {
|
||||
LayoutInflater.from(context).inflate(R.layout.shuttle_p_m2_traffic_light_view, this, true)
|
||||
}
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
super.onAttachedToWindow()
|
||||
CallerTrafficLightListenerManager.addListener(TAG, this)
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
CallerTrafficLightListenerManager.removeListener(TAG)
|
||||
}
|
||||
|
||||
/**
|
||||
* 展示红绿灯预警
|
||||
*
|
||||
* @param checkLightId 0-都是默认,1-红,2-黄,3-绿
|
||||
* @param lightSource 1:云端下发;2:自车感知
|
||||
*/
|
||||
override fun showTrafficLight(checkLightId: TrafficLightEnum, lightSource: DataSourceType) {
|
||||
super.showTrafficLight(checkLightId, lightSource)
|
||||
mCurrentLightId = checkLightId
|
||||
updateTrafficLightIcon(checkLightId)
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭红绿灯预警展示,并重制灯态
|
||||
*/
|
||||
override fun disableTrafficLight() {
|
||||
super.disableTrafficLight()
|
||||
UiThreadHandler.post {
|
||||
mCurrentLightId = TrafficLightEnum.BLACK
|
||||
this@M2PTrafficLightView.visibility = GONE
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param redNum 红灯倒计时
|
||||
* @param yellowNum 黄灯倒计时
|
||||
* @param greenNum 绿灯倒计时
|
||||
*/
|
||||
override fun changeCountdownTrafficLightNum(redNum: Int, yellowNum: Int, greenNum: Int) {
|
||||
super.changeCountdownTrafficLightNum(redNum, yellowNum, greenNum)
|
||||
resetView()
|
||||
when (mCurrentLightId) {
|
||||
TrafficLightEnum.RED -> changeCountdownRed(redNum)
|
||||
TrafficLightEnum.YELLOW -> changeCountdownYellow(yellowNum)
|
||||
TrafficLightEnum.GREEN -> changeCountdownGreen(greenNum)
|
||||
else -> UiThreadHandler.post { m2_p_traffic_light_time_tv.text = "" }
|
||||
}
|
||||
}
|
||||
|
||||
override fun changeCountdownRed(redNum: Int) {
|
||||
super.changeCountdownRed(redNum)
|
||||
UiThreadHandler.post {
|
||||
if (redNum > 0) {
|
||||
resetView()
|
||||
m2_p_traffic_light_time_tv.text = redNum.toString()
|
||||
} else {
|
||||
disableTrafficLightCountDown()
|
||||
m2_p_traffic_light_time_tv.text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun changeCountdownGreen(greenNum: Int) {
|
||||
super.changeCountdownGreen(greenNum)
|
||||
UiThreadHandler.post {
|
||||
if (greenNum > 0) {
|
||||
resetView()
|
||||
m2_p_traffic_light_time_tv.text = greenNum.toString()
|
||||
} else {
|
||||
disableTrafficLightCountDown()
|
||||
m2_p_traffic_light_time_tv.text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun changeCountdownYellow(yellowNum: Int) {
|
||||
super.changeCountdownYellow(yellowNum)
|
||||
UiThreadHandler.post {
|
||||
if (yellowNum > 0) {
|
||||
resetView()
|
||||
m2_p_traffic_light_time_tv.text = yellowNum.toString()
|
||||
} else {
|
||||
disableTrafficLightCountDown()
|
||||
m2_p_traffic_light_time_tv.text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新红绿灯icon
|
||||
*
|
||||
* @param lightId 0-都是默认,1-红,2-黄,3-绿
|
||||
*/
|
||||
private fun updateTrafficLightIcon(lightId: TrafficLightEnum) {
|
||||
UiThreadHandler.post {
|
||||
when (lightId) {
|
||||
TrafficLightEnum.RED -> {
|
||||
m2_p_traffic_light_iv.setBackgroundResource(R.drawable.shuttle_p_m2_light_red_nor)
|
||||
this@M2PTrafficLightView.visibility = VISIBLE
|
||||
}
|
||||
TrafficLightEnum.YELLOW -> {
|
||||
m2_p_traffic_light_iv.setBackgroundResource(R.drawable.shuttle_p_m2_light_yellow_nor)
|
||||
this@M2PTrafficLightView.visibility = VISIBLE
|
||||
}
|
||||
TrafficLightEnum.GREEN -> {
|
||||
m2_p_traffic_light_iv.setBackgroundResource(R.drawable.shuttle_p_m2_light_green_nor)
|
||||
this@M2PTrafficLightView.visibility = VISIBLE
|
||||
}
|
||||
else -> this@M2PTrafficLightView.visibility = GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun disableTrafficLightCountDown() {
|
||||
super.disableTrafficLightCountDown()
|
||||
UiThreadHandler.post {
|
||||
val layoutParams = layoutParams
|
||||
if (layoutParams is MarginLayoutParams) {
|
||||
val lp = layoutParams
|
||||
lp.width = resources.getDimension(R.dimen.dp_40).toInt()
|
||||
setLayoutParams(lp)
|
||||
m2_p_traffic_light_time_tv.visibility = GONE
|
||||
m2_p_traffic_light_bg.layoutParams.width =
|
||||
resources.getDimension(R.dimen.dp_40).toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun resetView() {
|
||||
val layoutParams = layoutParams
|
||||
if (layoutParams is MarginLayoutParams) {
|
||||
val lp = layoutParams
|
||||
lp.width = resources.getDimension(R.dimen.dp_60).toInt()
|
||||
setLayoutParams(lp)
|
||||
m2_p_traffic_light_time_tv.visibility = VISIBLE
|
||||
m2_p_traffic_light_bg.layoutParams.width =
|
||||
resources.getDimension(R.dimen.dp_60).toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package com.mogo.och.shuttle.passenger.ui.widget
|
||||
|
||||
import android.annotation.*
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import chassis.ChassisStatesOuterClass
|
||||
import com.mogo.eagle.core.function.api.autopilot.IMoGoBatteryManagementSystemListener
|
||||
import com.mogo.eagle.core.function.api.hmi.view.IViewControlListener
|
||||
import com.mogo.eagle.core.function.api.setting.IMoGoSkinModeChangeListener
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerBatteryManagementSystemListenerManager
|
||||
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager
|
||||
import com.mogo.eagle.core.function.call.hmi.CallerHmiViewControlListenerManager
|
||||
import com.mogo.eagle.core.function.call.setting.CallerSkinModeListenerManager
|
||||
import com.mogo.eagle.core.utilcode.kotlin.*
|
||||
import com.mogo.eagle.core.utilcode.util.ClickUtils
|
||||
import com.mogo.och.shuttle.passenger.R
|
||||
import kotlinx.android.synthetic.main.shuttle_p_m2_view_status_bar.view.progress
|
||||
import kotlinx.android.synthetic.main.shuttle_p_m2_view_status_bar.view.tv_power_cos
|
||||
import kotlinx.coroutines.*
|
||||
import me.jessyan.autosize.utils.AutoSizeUtils
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2023/2/14
|
||||
*/
|
||||
class M2StatusBarView @JvmOverloads constructor(
|
||||
context: Context, attrs: AttributeSet? = null
|
||||
) : ConstraintLayout(context, attrs), IViewControlListener, IMoGoSkinModeChangeListener,
|
||||
IMoGoBatteryManagementSystemListener {
|
||||
|
||||
companion object {
|
||||
const val TAG = "M2StatusBarView"
|
||||
}
|
||||
|
||||
@Volatile
|
||||
private var oldBmsSoc: Float = -1.0f
|
||||
|
||||
init {
|
||||
LayoutInflater.from(context).inflate(R.layout.shuttle_p_m2_view_status_bar, this, true)
|
||||
setBackgroundColor(Color.parseColor("#80FFFFFF"))
|
||||
isClickable = true
|
||||
isFocusable = true
|
||||
}
|
||||
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onAttachedToWindow() {
|
||||
super.onAttachedToWindow()
|
||||
post {
|
||||
val params: ViewGroup.LayoutParams = getLayoutParams()
|
||||
params.height = AutoSizeUtils.dp2px(context,40f)
|
||||
layoutParams = params
|
||||
}
|
||||
//添加view控制
|
||||
CallerHmiViewControlListenerManager.addListener(TAG,this)
|
||||
// 添加换肤监听
|
||||
CallerSkinModeListenerManager.addListener(TAG, this)
|
||||
//电量
|
||||
CallerBatteryManagementSystemListenerManager.addListener(TAG,this)
|
||||
|
||||
progress?.also {
|
||||
it.progress = 50
|
||||
}
|
||||
tv_power_cos?.also {
|
||||
it.text = "50%"
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSkinModeChange(skinMode: Int) {
|
||||
when (skinMode) {
|
||||
0 -> setStatusBarDarkOrLight(false)
|
||||
1 -> setStatusBarDarkOrLight(true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
CallerHmiViewControlListenerManager.removeListener(TAG)
|
||||
CallerSkinModeListenerManager.removeListener(TAG)
|
||||
CallerDevaToolsManager.hideStatusBar()
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onBatteryManagementSystemStates(states: ChassisStatesOuterClass.BMSSystemStates) {
|
||||
if (ClickUtils.isClickTooFrequent(this,1000)) {
|
||||
return
|
||||
}
|
||||
val bmsSoc = states.bmsSoc
|
||||
try {
|
||||
if (oldBmsSoc != bmsSoc ) {
|
||||
scope.launch {
|
||||
if(bmsSoc >1){
|
||||
progress?.also { it.progress = bmsSoc.toInt() }
|
||||
tv_power_cos?.also { it.text = "${bmsSoc.toInt()}%" }
|
||||
}else{
|
||||
val power = (bmsSoc * 100).toInt()
|
||||
progress?.also { it.progress = power }
|
||||
tv_power_cos?.also {it.text = "$power%" }
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
oldBmsSoc = bmsSoc
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
package com.mogo.och.shuttle.passenger.ui.widget
|
||||
|
||||
import android.animation.AnimatorSet
|
||||
import android.animation.ObjectAnimator
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.animation.AlphaAnimation
|
||||
import android.view.animation.Animation
|
||||
import android.widget.ImageView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import com.mogo.eagle.core.function.api.datacenter.union.IMoGoTurnLightListener
|
||||
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLamplightListenerManager
|
||||
import com.mogo.eagle.core.function.call.v2x.CallerTurnLightListenerManager
|
||||
import com.mogo.eagle.core.utilcode.util.ThreadUtils
|
||||
import com.mogo.och.shuttle.passenger.R
|
||||
import com.mogo.och.common.module.manager.light.TurnLightManager
|
||||
import kotlinx.android.synthetic.main.shuttle_p_jl_turn_light_status.view.left_nor_image
|
||||
import kotlinx.android.synthetic.main.shuttle_p_jl_turn_light_status.view.left_select_image
|
||||
import kotlinx.android.synthetic.main.shuttle_p_jl_turn_light_status.view.right_nor_image
|
||||
import kotlinx.android.synthetic.main.shuttle_p_jl_turn_light_status.view.right_select_image
|
||||
import kotlinx.android.synthetic.main.shuttle_p_jl_turn_light_status.view.turn_light_layout
|
||||
|
||||
/**
|
||||
* @author: wangmingjun
|
||||
* @date: 2023/2/13
|
||||
*/
|
||||
class M2TurnLightView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : ConstraintLayout(context, attrs, defStyleAttr),
|
||||
IMoGoTurnLightListener, TurnLightManager.TurnLightListener {
|
||||
|
||||
|
||||
companion object {
|
||||
private const val TAG = "TurnLightViewStatus"
|
||||
}
|
||||
|
||||
private var isLeftLight: Boolean = false
|
||||
private var isRightLight: Boolean = false
|
||||
private var isDisappear: Boolean = false
|
||||
|
||||
init {
|
||||
LayoutInflater.from(context)
|
||||
.inflate(R.layout.shuttle_p_m2_turn_light_status, this, true)
|
||||
}
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
super.onAttachedToWindow()
|
||||
CallerTurnLightListenerManager.addListener(TAG,this)
|
||||
|
||||
TurnLightManager.addTurnLightStatusChangeListener(TAG,this)
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
CallerChassisLamplightListenerManager.removeListener(TAG)
|
||||
CallerTurnLightListenerManager.removeListener(TAG)
|
||||
TurnLightManager.removeTurnLightStatusChangeListener(TAG)
|
||||
}
|
||||
|
||||
override fun hideTurnLightView() {
|
||||
ThreadUtils.runOnUiThread{
|
||||
if (!isDisappear) {
|
||||
isDisappear = true
|
||||
isLeftLight = false
|
||||
isRightLight = false
|
||||
animationDisappear()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun statusChange(newStatus: TurnLightManager.TurnLightStatus) {
|
||||
ThreadUtils.runOnUiThread {
|
||||
setTurnLight(newStatus)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转向灯动画
|
||||
*/
|
||||
private fun setTurnLight(directionLight: TurnLightManager.TurnLightStatus) {
|
||||
if (!isAttachedToWindow) {
|
||||
return
|
||||
}
|
||||
//根据左右进行显示和隐藏,实际要判断每个来的时间和频度
|
||||
when (directionLight) {
|
||||
TurnLightManager.TurnLightStatus.TURN_LIGHT_LEFT -> { //左转向
|
||||
if (!isLeftLight) {
|
||||
isLeftLight = true
|
||||
isRightLight = false
|
||||
isDisappear = false
|
||||
showNormalAnimation()
|
||||
left_select_image.visibility = View.VISIBLE
|
||||
right_select_image.visibility = View.GONE
|
||||
right_select_image.clearAnimation()
|
||||
setAnimation(left_select_image)
|
||||
}
|
||||
}
|
||||
TurnLightManager.TurnLightStatus.TURN_LIGHT_RIGHT -> { //右转向
|
||||
if (!isRightLight) {
|
||||
isRightLight = true
|
||||
isLeftLight = false
|
||||
isDisappear = false
|
||||
showNormalAnimation()
|
||||
left_select_image.visibility = View.GONE
|
||||
right_select_image.visibility = View.VISIBLE
|
||||
left_select_image.clearAnimation()
|
||||
setAnimation(right_select_image)
|
||||
}
|
||||
}
|
||||
TurnLightManager.TurnLightStatus.TURN_LIGHT_NONE -> { //消失
|
||||
if (!isDisappear) {
|
||||
isDisappear = true
|
||||
isLeftLight = false
|
||||
isRightLight = false
|
||||
animationDisappear()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//显示背景
|
||||
private fun showNormalAnimation() {
|
||||
val appearAnimation = AlphaAnimation(0f, 1.0f)
|
||||
appearAnimation.duration = 300
|
||||
val appearAnimationImage = AlphaAnimation(0f, 1.0f)
|
||||
appearAnimation.duration = 500
|
||||
turn_light_layout.startAnimation(appearAnimation)
|
||||
left_nor_image.startAnimation(appearAnimationImage)
|
||||
right_nor_image.startAnimation(appearAnimationImage)
|
||||
|
||||
turn_light_layout.visibility = View.VISIBLE
|
||||
left_nor_image.visibility = View.VISIBLE
|
||||
right_nor_image.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
//消失动画,当转向等数据为空时候
|
||||
private fun animationDisappear() {
|
||||
left_select_image.visibility = View.GONE
|
||||
right_select_image.visibility = View.GONE
|
||||
left_select_image.clearAnimation()
|
||||
right_select_image.clearAnimation()
|
||||
|
||||
left_nor_image.clearAnimation()
|
||||
right_nor_image.clearAnimation()
|
||||
turn_light_layout.clearAnimation()
|
||||
|
||||
val disappearAnimationLeft = AlphaAnimation(1.0f, 0f)
|
||||
disappearAnimationLeft.duration = 300
|
||||
|
||||
val disappearAnimationBg = AlphaAnimation(1.0f, 0f)
|
||||
disappearAnimationBg.duration = 500
|
||||
|
||||
left_nor_image.startAnimation(disappearAnimationLeft)
|
||||
right_nor_image.startAnimation(disappearAnimationLeft)
|
||||
turn_light_layout.startAnimation(disappearAnimationBg)
|
||||
|
||||
disappearAnimationLeft.setAnimationListener(object : Animation.AnimationListener {
|
||||
override fun onAnimationRepeat(p0: Animation?) {
|
||||
}
|
||||
|
||||
override fun onAnimationStart(p0: Animation?) {
|
||||
}
|
||||
|
||||
override fun onAnimationEnd(p0: Animation?) {
|
||||
left_nor_image.visibility = View.GONE
|
||||
right_nor_image.visibility = View.GONE
|
||||
}
|
||||
})
|
||||
|
||||
disappearAnimationBg.setAnimationListener(object : Animation.AnimationListener {
|
||||
override fun onAnimationRepeat(p0: Animation?) {
|
||||
}
|
||||
|
||||
override fun onAnimationStart(p0: Animation?) {
|
||||
}
|
||||
|
||||
override fun onAnimationEnd(p0: Animation?) {
|
||||
turn_light_layout.visibility = View.GONE
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//实现图片闪烁效果
|
||||
private fun setAnimation(imageView: ImageView) {
|
||||
val animationSet = AnimatorSet()
|
||||
val valueAnimator = ObjectAnimator.ofFloat(imageView, "alpha", 0f, 1.0f)
|
||||
val valueAnimatorDisappear = ObjectAnimator.ofFloat(imageView, "alpha", 1.0f, 0f)
|
||||
valueAnimator.duration = 1000
|
||||
valueAnimatorDisappear.duration = 800
|
||||
valueAnimator.repeatCount = -1
|
||||
valueAnimatorDisappear.repeatCount = -1
|
||||
animationSet.playTogether(valueAnimatorDisappear, valueAnimator)
|
||||
animationSet.start()
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user