Merge remote-tracking branch 'origin/dev_robotaxi-d_241112_6.8.0' into dev_robotaxi-d_241112_6.8.0

This commit is contained in:
donghongyu
2024-11-19 11:23:02 +08:00
62 changed files with 1892 additions and 132 deletions

View File

@@ -64,8 +64,8 @@ dependencies {
implementation rootProject.ext.dependencies.amapnavi3dmap
implementation rootProject.ext.dependencies.rxandroid
// 串口链接
implementation rootProject.ext.dependencies.serialport
// 硬件管理
implementation project(":libraries:mogo-hardware-devices")
implementation rootProject.ext.dependencies.arouter
kapt rootProject.ext.dependencies.aroutercompiler

View File

@@ -1,7 +1,6 @@
package com.mogo.och.common.module.manager.scnner
import android.net.Uri
import com.mogo.commons.AbsMogoApplication
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_BUS_P
@@ -9,17 +8,17 @@ import com.mogo.eagle.core.utilcode.util.GsonUtils
import com.mogo.eagle.core.utilcode.util.StringUtils
import com.mogo.och.common.module.biz.lansocket.IOchLanPassengerStatusListener
import com.mogo.och.common.module.biz.lansocket.LoginLanPassengerSocket
import com.mogo.och.common.module.manager.socket.lan.bean.WriteOffDevicesMsg
import com.mogo.och.common.module.manager.socket.lan.bean.WriteOffMsg
import com.mogo.och.common.module.constant.OchCommonConst
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
import com.mogo.och.common.module.manager.socket.lan.LanSocketManager
import com.mogo.support.serialport.client.SerialPortManager
import com.mogo.support.serialport.client.SerialPortManager.SERVICE_STATE
import com.mogo.support.serialport.client.listener.OnDeviceVerificationListener
import com.mogo.support.serialport.client.listener.OnSerialPortListener
import com.mogo.support.serialport.common.verification.UnpackStatus
import com.mogo.support.serialport.common.verification.data.VerificationActiveData
import com.mogo.och.common.module.manager.socket.lan.bean.WriteOffDevicesMsg
import com.mogo.och.common.module.manager.socket.lan.bean.WriteOffMsg
import com.mogo.support.device.manager.SerialPortManager
import com.mogo.support.device.manager.bean.VerificationData
import com.mogo.support.serialport.common.core.DeviceType
import com.mogo.support.device.DevicesManager
import com.mogo.support.device.IBindStateChangeListener
import com.mogo.support.device.IVerificationAutoListener
import java.util.concurrent.ConcurrentHashMap
import kotlin.properties.Delegates
@@ -28,7 +27,6 @@ object ScannerManager : IOchLanPassengerStatusListener {
private val TAG = "ScannerManager"
private var serialPortManager = SerialPortManager()
private val stateChanageListeners: ConcurrentHashMap<String, StateChangeListener> =
ConcurrentHashMap()
@@ -36,8 +34,11 @@ object ScannerManager : IOchLanPassengerStatusListener {
private var bindStatus: BindStatus by Delegates.observable(BindStatus.NOTHING) { _, oldV, newV ->
if (oldV != newV) {
try {
CallerLogger.d(SceneConstant.M_OCHCOMMON + TAG, "扫码枪状态发生变化old:${oldV}_new${newV}")
if(newV!= BindStatus.BIND_SUCCEED) {
CallerLogger.d(
SceneConstant.M_OCHCOMMON + TAG,
"扫码枪状态发生变化old:${oldV}_new${newV}"
)
if (newV != BindStatus.BIND_SUCCEED) {
dispatchMsg(newV)
}
if (stateChanageListeners.size > 0) {
@@ -65,41 +66,58 @@ object ScannerManager : IOchLanPassengerStatusListener {
}
}
private val onDeviceVerificationListener = object :OnDeviceVerificationListener(){
override fun onSerialPortState(
private val onDeviceVerificationListener = object : IVerificationAutoListener {
override fun onDeviceState(
path: String?,
deviceType: Byte,
isOpen: Boolean,
throwableMessage: String?
message: String?
) {
CallerLogger.d(
M_BUS_P + TAG,
"path ${path}---isOpen${isOpen}--throwableMessage${throwableMessage}"
super.onDeviceState(path, deviceType, isOpen, message)
var deviceTypeString = "未知"
if (deviceType == DeviceType.VERIFICATION_SK87R) {
deviceTypeString = "(SK87R)"
} else if (deviceType == DeviceType.VERIFICATION_Q350) {
deviceTypeString = "(Q350)"
}
val msg =
"地址:${path} 设备类型:${deviceTypeString} 是否打开:${isOpen} 消息:${message}"
CallerLogger.d(M_BUS_P + TAG, msg)
OchChainLogManager.writeChainLogScanner(
TAG + "onSerialPortState",
"扫码枪是否打开:${msg}"
)
OchChainLogManager.writeChainLogScanner(TAG +"onSerialPortState","扫码枪是否打开:path${path}_isOpen${isOpen}_throwableMessage${throwableMessage}")
openStatus = if (isOpen) {
sendWriteOffDevicesMessage2Driver(true,"扫码枪打开成功")
sendWriteOffDevicesMessage2Driver(true, "扫码枪打开成功")
OpenStatus.Open
} else {
sendWriteOffDevicesMessage2Driver(false,"扫码枪打开错误:${throwableMessage}_${path}")
sendWriteOffDevicesMessage2Driver(
false,
"扫码枪打开错误:${msg}_${path}_${deviceTypeString}"
)
OpenStatus.Unopen
}
}
override fun onActiveDataReceive(data: VerificationActiveData?) {
OchChainLogManager.writeChainLogScanner(TAG +"onActiveDataReceive","扫码结果data:${data}")
override fun onReceive(data: VerificationData?) {
OchChainLogManager.writeChainLogScanner(
TAG + "onActiveDataReceive",
"扫码结果data:${data}"
)
data?.let {
if(data.unpackStatus==UnpackStatus.SUCCEED){
if (data.unpackStatus.isNullOrEmpty()) {
"数据类型${it.dataType.name}"
CallerLogger.d(M_BUS_P + TAG, "data $it")
if(!StringUtils.isEmpty(it.payload)){
if (!StringUtils.isEmpty(it.payload)) {
parseParams(it.payload)
}else{
} else {
CallerLogger.d(M_BUS_P + TAG, "数据错误")
sendWriteOffMessage2Driver("扫码数据为空")
}
}else{
sendWriteOffMessage2Driver("解包失败")
CallerLogger.d(M_BUS_P + TAG, "解包失败")
} else {
sendWriteOffMessage2Driver("解包失败:${data.unpackStatus}")
CallerLogger.d(M_BUS_P + TAG, "解包失败:${data.unpackStatus}")
}
}
}
@@ -107,45 +125,47 @@ object ScannerManager : IOchLanPassengerStatusListener {
}
private val onSerialPortListener = object :OnSerialPortListener{
override fun onServiceState(serviceState: Int) {
OchChainLogManager.writeChainLogScanner(TAG +"bindStatus","绑定服务结果:serviceState:${serviceState}")
when (serviceState) {
SERVICE_STATE.BIND_SUCCEED -> {
private val onSerialPortListener = object : IBindStateChangeListener {
override fun onServiceState(state: Int) {
OchChainLogManager.writeChainLogScanner(
TAG + "bindStatus",
"绑定服务结果:serviceState:${state}"
)
when (state) {
SerialPortManager.SERVICE_STATE.BIND_SUCCEED -> {
CallerLogger.d(M_BUS_P + TAG, "服务绑定成功")
bindStatus = BindStatus.BIND_SUCCEED
serialPortManager.openVerificationDevice(onDeviceVerificationListener)
}
SERVICE_STATE.BIND_FAILURE_UNINSTALLED -> {
SerialPortManager.SERVICE_STATE.BIND_FAILURE_UNINSTALLED -> {
CallerLogger.d(M_BUS_P + TAG, "服务绑定失败未安装串口服务端APP")
bindStatus = BindStatus.BIND_FAILURE_UNINSTALLED
}
SERVICE_STATE.BIND_FAILURE_NO_PERMISSION_NOT_FOUND -> {
CallerLogger.d(M_BUS_P + TAG, "服务绑定失败:没有绑定权限或找不到服务(如果是此状态,基本上安装后就可以找到,主要就是权限问题)")
SerialPortManager.SERVICE_STATE.BIND_FAILURE_NO_PERMISSION_NOT_FOUND -> {
CallerLogger.d(
M_BUS_P + TAG,
"服务绑定失败:没有绑定权限或找不到服务(如果是此状态,基本上安装后就可以找到,主要就是权限问题)"
)
bindStatus = BindStatus.BIND_FAILURE_NO_PERMISSION_NOT_FOUND
}
SERVICE_STATE.EXCEPTION -> {
SerialPortManager.SERVICE_STATE.EXCEPTION -> {
CallerLogger.d(M_BUS_P + TAG, "服务被异常销毁")
bindStatus = BindStatus.EXCEPTION
}
else -> {}
}
}
// 查询串口
override fun onFindSerialPort(paths: Array<out String>?) {
CallerLogger.d(M_BUS_P + TAG, "$paths")
OchChainLogManager.writeChainLogScanner(TAG +"onFindSerialPort","查询串口:${paths}")
if(paths==null) {
bindStatus = BindStatus.BIND_FAILURE_NO_PERMISSION_NOT_FOUND
}
}
}
init {
//监听司机端消息
LoginLanPassengerSocket.addListener(TAG,this)
serialPortManager.bindService(AbsMogoApplication.getApp(), onSerialPortListener)//绑定服务
LoginLanPassengerSocket.addListener(TAG, this)
DevicesManager.addBindStateChangeListener(TAG, onSerialPortListener)
DevicesManager.addVerificationListener(TAG, onDeviceVerificationListener)
}
fun addStateChangeListener(tag: String, listener: StateChangeListener) {
@@ -157,7 +177,7 @@ object ScannerManager : IOchLanPassengerStatusListener {
override fun onDriverConnectChangeListener(isConnect: Boolean) {
super.onDriverConnectChangeListener(isConnect)
if(isConnect) {
if (isConnect) {
sendScannerState()
}
}
@@ -168,17 +188,17 @@ object ScannerManager : IOchLanPassengerStatusListener {
val mutableMapOf = mutableMapOf<String, Any>()
queryParameterNames.forEach {
val queryParameter = parse.getQueryParameter(it)
if(it!=null&&queryParameter!=null){
if (it != null && queryParameter != null) {
mutableMapOf[it] = queryParameter
}
}
if(mutableMapOf.isNotEmpty()){
if (mutableMapOf.isNotEmpty()) {
if (stateChanageListeners.size > 0) {
stateChanageListeners.forEach {
it.value.parseData(mutableMapOf,payload)
it.value.parseData(mutableMapOf, payload)
}
}
}else{
} else {
sendWriteOffMessage2Driver("扫码参数数据为空:${payload}")
}
@@ -187,7 +207,7 @@ object ScannerManager : IOchLanPassengerStatusListener {
/**
* @param isConnectScanner 是否打开设备
*/
private fun sendWriteOffDevicesMessage2Driver(isConnectScanner:Boolean, message:String){
private fun sendWriteOffDevicesMessage2Driver(isConnectScanner: Boolean, message: String) {
val msg = WriteOffDevicesMsg(isConnectScanner, message)
CallerLogger.d(M_BUS_P + TAG, "sendTaskDetailsToClients = " + GsonUtils.toJson(msg))
LanSocketManager.sendMsgToServer(msg)
@@ -196,8 +216,8 @@ object ScannerManager : IOchLanPassengerStatusListener {
/**
* 打开设备后数据异常
*/
private fun sendWriteOffMessage2Driver(message:String){
val msg = WriteOffMsg(false, "", 0, "", message,"")
private fun sendWriteOffMessage2Driver(message: String) {
val msg = WriteOffMsg(false, "", 0, "", message, "")
CallerLogger.d(M_BUS_P + TAG, "sendTaskDetailsToClients = " + GsonUtils.toJson(msg))
LanSocketManager.sendMsgToServer(msg)
}
@@ -206,12 +226,12 @@ object ScannerManager : IOchLanPassengerStatusListener {
* 链接司机屏后向司机屏同步扫码枪状态
*/
private fun sendScannerState() {
if(bindStatus == BindStatus.BIND_SUCCEED && openStatus == OpenStatus.Open){
sendWriteOffDevicesMessage2Driver(true,"扫码枪打开状态")
}else{
if(bindStatus == BindStatus.BIND_SUCCEED && openStatus == OpenStatus.Unopen){
sendWriteOffDevicesMessage2Driver(false,"绑定成功、打开失败")
}else{
if (bindStatus == BindStatus.BIND_SUCCEED && openStatus == OpenStatus.Open) {
sendWriteOffDevicesMessage2Driver(true, "扫码枪打开状态")
} else {
if (bindStatus == BindStatus.BIND_SUCCEED && openStatus == OpenStatus.Unopen) {
sendWriteOffDevicesMessage2Driver(false, "绑定成功、打开失败")
} else {
dispatchMsg(bindStatus)
}
}
@@ -221,16 +241,19 @@ object ScannerManager : IOchLanPassengerStatusListener {
when (newV) {
BindStatus.BIND_FAILURE_UNINSTALLED -> {
// 服务绑定失败未安装串口服务端APP
sendWriteOffDevicesMessage2Driver(false,"服务绑定失败未安装串口服务端APP")
sendWriteOffDevicesMessage2Driver(false, "服务绑定失败未安装串口服务端APP")
}
BindStatus.BIND_FAILURE_NO_PERMISSION_NOT_FOUND -> {
// 服务绑定失败:没有绑定权限或找不到服务(如果是此状态,基本上安装后就可以找到,主要就是权限问题)
sendWriteOffDevicesMessage2Driver(false,"服务绑定失败:没有绑定权限或找不到服务")
sendWriteOffDevicesMessage2Driver(false, "服务绑定失败:没有绑定权限或找不到服务")
}
BindStatus.EXCEPTION -> {
// 扫码枪open错误
sendWriteOffDevicesMessage2Driver(false,"扫码枪打开错误")
sendWriteOffDevicesMessage2Driver(false, "扫码枪打开错误")
}
BindStatus.NOTHING -> {}
else -> {}
}
@@ -240,7 +263,7 @@ object ScannerManager : IOchLanPassengerStatusListener {
}
enum class BindStatus {
BIND_SUCCEED, BIND_FAILURE_UNINSTALLED ,BIND_FAILURE_NO_PERMISSION_NOT_FOUND,EXCEPTION,NOTHING
BIND_SUCCEED, BIND_FAILURE_UNINSTALLED, BIND_FAILURE_NO_PERMISSION_NOT_FOUND, EXCEPTION, NOTHING
}
enum class OpenStatus {

View File

@@ -154,12 +154,20 @@ class AutopilotStateModel : ViewModel(), IOchAutopilotStatusListener, ILineCall
override fun startAutopilotTimeOut() {
OchChainLogManager.writeChainLog("自驾信息","启动自驾超时失败")
startAutopilotFail()
if(OchAutoPilotStatusListenerManager.autopilotState == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING){
autopilotStateChange()
}else {
startAutopilotFail()
}
}
override fun startAutopilotFailure(startFailedCode: String?, startFailedMessage: String?) {
OchChainLogManager.writeChainLog("自驾信息","底盘强制失败原因:${startFailedCode}_${startFailedMessage}")
startAutopilotFail()
if(OchAutoPilotStatusListenerManager.autopilotState == IMoGoAutopilotStatusListener.STATUS_AUTOPILOT_RUNNING){
autopilotStateChange()
}else {
startAutopilotFail()
}
}
private fun startAutopilotFail(){

View File

@@ -14,6 +14,7 @@ import com.mogo.eagle.core.network.MoGoRetrofitFactory
import com.mogo.eagle.core.utilcode.util.GsonUtils
import com.mogo.eagle.core.utilcode.util.NetworkUtils
import com.mogo.eagle.core.utilcode.util.UiThreadHandler
import com.mogo.och.common.module.biz.lansocket.LoginLanPassengerSocket
import com.mogo.och.common.module.constant.OchCommonConst
import com.mogo.och.common.module.network.OchCommonServiceCallback
import com.mogo.och.common.module.network.OchCommonSubscribeImpl
@@ -188,7 +189,7 @@ object MediaDataSourceManager {
private fun getMediaDataFromMis(callback: OchCommonServiceCallback<MediaDataResp>) {
MediaPlayLogger.printInfoLog("getMediaDataFromMis准备发送请求driverSn=$driverSn")
mNetworkService
?.queryMediaDataFromMis(sn = driverSn, screenType = "2",)
?.queryMediaDataFromMis(sn = LoginLanPassengerSocket.driverSn, screenType = "2",)
?.transformTry()
?.subscribe(OchCommonSubscribeImpl(context, callback, "getMediaDataFromMis"))
}

View File

@@ -62,9 +62,9 @@ class MediaPlayerFragment :
arrayListOf.addAll(list)
UiThreadHandler.post {
if (isNewData) {
imageVideoRotationView.setNewMediaData(arrayListOf)
imageVideoRotationView?.setNewMediaData(arrayListOf)
} else {
imageVideoRotationView.setMediaData(arrayListOf)
imageVideoRotationView?.setMediaData(arrayListOf)
}
}
}

View File

@@ -1085,12 +1085,18 @@ public class OrderModel {
parameters.vehicleType = VEHICLE_TYPE;
if (parameters.autoPilotLine == null) {
parameters.autoPilotLine = new AutopilotControlParameters.AutoPilotLine(
busRoutesResult.getLineId(), busRoutesResult.getName(),
busRoutesResult.csvFileUrl, busRoutesResult.csvFileMd5,
busRoutesResult.txtFileUrl, busRoutesResult.txtFileMd5,
busRoutesResult.contrailSaveTime, busRoutesResult.carModel,
busRoutesResult.csvFileUrlDPQP, busRoutesResult.csvFileMd5DPQP,
busRoutesResult.txtFileUrlDPQP, busRoutesResult.txtFileMd5DPQP,
busRoutesResult.getLineId(),
busRoutesResult.getName(),
busRoutesResult.csvFileUrl==null?"":busRoutesResult.csvFileUrl,
busRoutesResult.csvFileMd5==null?"":busRoutesResult.csvFileMd5,
busRoutesResult.txtFileUrl==null?"":busRoutesResult.txtFileUrl,
busRoutesResult.txtFileMd5==null?"":busRoutesResult.txtFileMd5,
busRoutesResult.contrailSaveTime,
busRoutesResult.carModel,
busRoutesResult.csvFileUrlDPQP,
busRoutesResult.csvFileMd5DPQP,
busRoutesResult.txtFileUrlDPQP,
busRoutesResult.txtFileMd5DPQP,
busRoutesResult.contrailSaveTimeDPQP);
}

View File

@@ -129,17 +129,12 @@ public class BusTrajectoryManager {
} else {
mAutoPilotLine.setLineId(routesResult.getLineId());
mAutoPilotLine.setLineName(routesResult.getName());
mAutoPilotLine.setTrajUrl(routesResult.csvFileUrl);
mAutoPilotLine.setTrajMd5(routesResult.csvFileMd5);
mAutoPilotLine.setStopUrl(routesResult.txtFileUrl);
mAutoPilotLine.setStopMd5(routesResult.txtFileMd5);
mAutoPilotLine.setTrajUrl(routesResult.csvFileUrl==null?"":routesResult.csvFileUrl);
mAutoPilotLine.setTrajMd5(routesResult.csvFileMd5==null?"":routesResult.csvFileMd5);
mAutoPilotLine.setStopUrl(routesResult.txtFileUrl==null?"":routesResult.txtFileUrl);
mAutoPilotLine.setStopMd5(routesResult.txtFileMd5==null?"":routesResult.txtFileMd5);
mAutoPilotLine.setTimestamp(routesResult.contrailSaveTime);
mAutoPilotLine.setVehicleModel(routesResult.carModel);
mAutoPilotLine.setTrajUrl_dpqp(routesResult.csvFileUrlDPQP);
mAutoPilotLine.setTrajMd5_dpqp(routesResult.csvFileMd5DPQP);
mAutoPilotLine.setStopUrl_dpqp(routesResult.txtFileUrlDPQP);
mAutoPilotLine.setStopMd5_dpqp(routesResult.txtFileMd5DPQP);
mAutoPilotLine.setTimestamp_dpqp(routesResult.contrailSaveTimeDPQP);
mAutoPilotLine.setVehicleModel(routesResult.carModel==null?"":routesResult.carModel);
}
}
}

View File

@@ -72,11 +72,11 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_71"
app:layout_constraintEnd_toEndOf="@+id/viewLimitingVelocity"
app:layout_constraintEnd_toEndOf="parent"
app:layout_goneMarginEnd="40dp"
app:layout_goneMarginTop="@dimen/dp_236"
android:visibility="invisible"
app:layout_constraintTop_toBottomOf="@+id/viewLimitingVelocity"/>
app:layout_constraintTop_toBottomOf="@+id/ivCameraIcon"/>
<!--消息盒子选择入口-->
<com.mogo.eagle.core.function.hmi.ui.msgbox.DriverMsgBoxButtonView
@@ -85,7 +85,7 @@
android:layout_height="@dimen/dp_142"
android:layout_marginTop="15dp"
android:layout_marginEnd="25dp"
app:layout_constraintRight_toLeftOf="@id/viewLimitingVelocity"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ivCameraIcon" />
<!--消息盒子打开视图-->
<com.mogo.eagle.core.function.hmi.ui.msgbox.DriverMsgBoxListView

View File

@@ -0,0 +1,601 @@
{
"formatVersion": 1,
"database": {
"version": 4,
"identityHash": "1d1bd5c3b1770e4bc24252f26791f036",
"entities": [
{
"tableName": "contrail_data_table",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `line_id` INTEGER, `csv_file_url` TEXT, `csv_file_md5` TEXT, `txt_file_url` TEXT, `txt_file_md5` TEXT, `contrail_save_time` INTEGER, `md5` TEXT)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "lineId",
"columnName": "line_id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "csvFileUrl",
"columnName": "csv_file_url",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "csvFileMd5",
"columnName": "csv_file_md5",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "txtFileUrl",
"columnName": "txt_file_url",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "txtFileMd5",
"columnName": "txt_file_md5",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "contrailSaveTime",
"columnName": "contrail_save_time",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "md5",
"columnName": "md5",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": true
},
"indices": [
{
"name": "index_contrail_data_table_line_id",
"unique": false,
"columnNames": [
"line_id"
],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_contrail_data_table_line_id` ON `${TABLE_NAME}` (`line_id`)"
},
{
"name": "index_contrail_data_table_md5",
"unique": false,
"columnNames": [
"md5"
],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_contrail_data_table_md5` ON `${TABLE_NAME}` (`md5`)"
}
],
"foreignKeys": []
},
{
"tableName": "line_data_table",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `line_id` INTEGER, `line_name` TEXT, `end_station_name` TEXT, `line_get_time` INTEGER NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "lineId",
"columnName": "line_id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "lineName",
"columnName": "line_name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "endStationName",
"columnName": "end_station_name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "linegetTime",
"columnName": "line_get_time",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": true
},
"indices": [
{
"name": "index_line_data_table_line_id",
"unique": false,
"columnNames": [
"line_id"
],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_line_data_table_line_id` ON `${TABLE_NAME}` (`line_id`)"
}
],
"foreignKeys": []
},
{
"tableName": "site_data_table",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `site_id` INTEGER, `line_id` INTEGER, `name` TEXT, `name_kr` TEXT, `seq` INTEGER, `gcj_lon` REAL, `gcj_lat` REAL, `lon` REAL, `lat` REAL, `introduction` TEXT, `is_play_tts` INTEGER, `md5` TEXT, `videoList` TEXT)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "siteId",
"columnName": "site_id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "lineId",
"columnName": "line_id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "nameKr",
"columnName": "name_kr",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "seq",
"columnName": "seq",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "gcjLon",
"columnName": "gcj_lon",
"affinity": "REAL",
"notNull": false
},
{
"fieldPath": "gcjLat",
"columnName": "gcj_lat",
"affinity": "REAL",
"notNull": false
},
{
"fieldPath": "lon",
"columnName": "lon",
"affinity": "REAL",
"notNull": false
},
{
"fieldPath": "lat",
"columnName": "lat",
"affinity": "REAL",
"notNull": false
},
{
"fieldPath": "introduction",
"columnName": "introduction",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "isPlayTts",
"columnName": "is_play_tts",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "md5",
"columnName": "md5",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "videoListDB",
"columnName": "videoList",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": true
},
"indices": [
{
"name": "index_site_data_table_site_id",
"unique": false,
"columnNames": [
"site_id"
],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_site_data_table_site_id` ON `${TABLE_NAME}` (`site_id`)"
},
{
"name": "index_site_data_table_line_id",
"unique": false,
"columnNames": [
"line_id"
],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_site_data_table_line_id` ON `${TABLE_NAME}` (`line_id`)"
}
],
"foreignKeys": []
},
{
"tableName": "task_data_table",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `task_id` INTEGER, `line_id` INTEGER, `task_data` INTEGER, `task_start_time` INTEGER, `start_time` INTEGER, `end_time` INTEGER, `task_get_time` INTEGER NOT NULL, `status` INTEGER)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "taskId",
"columnName": "task_id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "lineId",
"columnName": "line_id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "taskDate",
"columnName": "task_data",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "taskStartTime",
"columnName": "task_start_time",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "startTime",
"columnName": "start_time",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "endtime",
"columnName": "end_time",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "taskgetTime",
"columnName": "task_get_time",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "status",
"columnName": "status",
"affinity": "INTEGER",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": true
},
"indices": [
{
"name": "index_task_data_table_task_id",
"unique": false,
"columnNames": [
"task_id"
],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_task_data_table_task_id` ON `${TABLE_NAME}` (`task_id`)"
},
{
"name": "index_task_data_table_line_id",
"unique": false,
"columnNames": [
"line_id"
],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_task_data_table_line_id` ON `${TABLE_NAME}` (`line_id`)"
}
],
"foreignKeys": []
},
{
"tableName": "used_task_data_table",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `task_id` INTEGER, `line_id` INTEGER, `site_id` INTEGER, `line_name` TEXT, `name` TEXT, `name_kr` TEXT, `seq` INTEGER, `gcj_lon` REAL, `gcj_lat` REAL, `lon` REAL, `lat` REAL, `driving_status` INTEGER, `leaving` INTEGER, `arrived_time` INTEGER, `leave_time` INTEGER, `introduction` TEXT, `is_play_tts` INTEGER, `event_save_time` INTEGER NOT NULL, `videoList` TEXT)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "taskId",
"columnName": "task_id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "lineId",
"columnName": "line_id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "siteId",
"columnName": "site_id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "lineName",
"columnName": "line_name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "nameKr",
"columnName": "name_kr",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "seq",
"columnName": "seq",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "gcjLon",
"columnName": "gcj_lon",
"affinity": "REAL",
"notNull": false
},
{
"fieldPath": "gcjLat",
"columnName": "gcj_lat",
"affinity": "REAL",
"notNull": false
},
{
"fieldPath": "lon",
"columnName": "lon",
"affinity": "REAL",
"notNull": false
},
{
"fieldPath": "lat",
"columnName": "lat",
"affinity": "REAL",
"notNull": false
},
{
"fieldPath": "drivingStatus",
"columnName": "driving_status",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "leaving",
"columnName": "leaving",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "arrivedTime",
"columnName": "arrived_time",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "leaveTime",
"columnName": "leave_time",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "introduction",
"columnName": "introduction",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "isPlayTts",
"columnName": "is_play_tts",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "eventSaveTime",
"columnName": "event_save_time",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "videoList",
"columnName": "videoList",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": true
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "event_data_table",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `event_type` TEXT, `lineId` INTEGER, `lineName` TEXT, `task_id` INTEGER, `task_start_time` INTEGER, `business_time` INTEGER, `write_version` INTEGER, `site_id` INTEGER, `seq` INTEGER, `driver_id` INTEGER, `event_save_time` INTEGER NOT NULL, `update_status` INTEGER NOT NULL, `msg_id` TEXT, `update_time` INTEGER)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "eventType",
"columnName": "event_type",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "lineId",
"columnName": "lineId",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "lineName",
"columnName": "lineName",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "taskId",
"columnName": "task_id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "taskStartTime",
"columnName": "task_start_time",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "businessTime",
"columnName": "business_time",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "writeVersion",
"columnName": "write_version",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "siteId",
"columnName": "site_id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "seq",
"columnName": "seq",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "driverId",
"columnName": "driver_id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "eventSaveTime",
"columnName": "event_save_time",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "updateStatus",
"columnName": "update_status",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "msgId",
"columnName": "msg_id",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "upDateTime",
"columnName": "update_time",
"affinity": "INTEGER",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": true
},
"indices": [
{
"name": "index_event_data_table_event_save_time",
"unique": false,
"columnNames": [
"event_save_time"
],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_event_data_table_event_save_time` ON `${TABLE_NAME}` (`event_save_time`)"
}
],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '1d1bd5c3b1770e4bc24252f26791f036')"
]
}
}

View File

@@ -17,7 +17,7 @@ data class ShuttleEventRequest(val requestId: String, val sn: String, val busine
var tempEvent: Event?=null
waitUpdateEvent.forEach {
tempEvent = Event(it.eventType,
EventData(it.taskId,it.businessTime,it.writeVersion,it.siteId,it.seq,it.driverId)
EventData(it.taskId,it.businessTime,it.writeVersion,it.siteId,it.seq,it.driverId,it.msgId)
)
eventList4Request.add(tempEvent!!)
}
@@ -35,5 +35,6 @@ data class EventData(
var writeVersion: Long?,
var siteId: Long?,
var seq: Int?,
var driverId:Long?
var driverId:Long?,
var msgId:String?
)

View File

@@ -54,11 +54,16 @@ class BusRoutesResponse : BaseData() {
temp?.seq = (taskAndsite.seq ?: 0)
temp?.siteId = if (taskAndsite.siteId == null) 0 else taskAndsite.siteId!!.toInt()
if(!taskAndsite.videoList.isNullOrEmpty()){
val list = GsonUtils.fromJson<List<SiteIntroduce>>(
taskAndsite.videoList,
object : TypeToken<List<SiteIntroduce?>?>() {}.type
)
temp?.videoList = list.toMutableList()
try {
val list = GsonUtils.fromJson<List<SiteIntroduce>>(
taskAndsite.videoList,
object : TypeToken<List<SiteIntroduce?>?>() {}.type
)
temp?.videoList = list.toMutableList()
}catch (e:Exception){
temp?.videoList = null
}
}
result.add(temp!!)
// 正在进行中的任务

View File

@@ -55,6 +55,10 @@ object EventModel : EventDb.EventCallback {
private fun updateEvent(){
if(isUpdating.get()){
OchChainLogManager.writeChainLogDb("上报event","正在上传 等待下一次轮训 ${Thread.currentThread().name}")
return
}
isUpdating.set(true)
createDefault.onNext(isUpdating.get())
ThreadUtils.getSinglePool().submit {
@@ -72,6 +76,7 @@ object EventModel : EventDb.EventCallback {
override fun onSuccess(data: BaseData?) {
waitUpdateEvent.forEach {
it.updateStatus = EventDataBean.updated
it.upDateTime = System.currentTimeMillis()
}
OchChainLogManager.writeChainLogDb("上报event成功","$transformDb2Net ${Thread.currentThread().name}")
EventDb.saveUpdateSuccess(waitUpdateEvent)

View File

@@ -457,6 +457,10 @@ object OrderModel {
ToastUtils.showShort(ResourcesUtils.getString(R.string.shuttle_logout_error))
return@execute
}
if(RepositoryManager.haveRunningTask()){
ToastUtils.showShort(ResourcesUtils.getString(R.string.shuttle_logout_error_running))
return@execute
}
MapMakerManager.removeAllMapMarkerByOwner(TAG)
BusTrajectoryManager.getInstance().stopTrajReqLoop();
LoginStatusManager.loginOut()

View File

@@ -132,6 +132,7 @@ object ThirdDeviceData {
busRoutesResult.name = lineInfo.lineName
busRoutesResult.taskId = LineModel.currentTask!!.taskId!!.toInt()
busRoutesResult.taskTime = LineModel.currentTask!!.taskStartTime!!
busRoutesResult.writeVersion = System.currentTimeMillis()
val data = BusTransferData(if (LoginStatusManager.isLogin()) 1 else 0, busRoutesResult)
val msg = TaskDetailsMsg(GsonUtils.toJson(data), BusinessType.shuttle)
d(M_BUS + TAG, "sendTaskDetailsToClients = " + GsonUtils.toJson(msg))

View File

@@ -32,6 +32,10 @@ interface IRepository {
fun reportCabinEvent(context: Context?, data: ShuttleEventRequest?, callback: OchCommonServiceCallback<BaseData?>?)
fun haveRunningTask(): Boolean{
return false
}
fun release()
}

View File

@@ -96,6 +96,10 @@ object RepositoryManager {
repository?.queryWriteoffCount(context,taskId,siteId,callback)
}
fun haveRunningTask():Boolean{
return repository?.haveRunningTask()?:false
}
fun haveDataWaitSyn(): Boolean {
if(ProjectUtils.isSaas()&&AppIdentityModeUtils.isShuttle(FunctionBuildConfig.appIdentityMode)) {

View File

@@ -12,6 +12,7 @@ import com.mogo.commons.env.Project
import com.mogo.commons.env.ProjectUtils
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.utilcode.util.FileUtils
import com.mogo.och.weaknet.repository.db.bean.ContrailDataBean
import com.mogo.och.weaknet.repository.db.bean.EventDataBean
import com.mogo.och.weaknet.repository.db.bean.LineDataBean
@@ -30,7 +31,7 @@ import java.io.File
//entities指定该数据库有哪些表多张表就逗号分隔
//version指定数据库版本号升级时需要用到
//数据库继承自RoomDatabase
@Database(entities = [ContrailDataBean::class, LineDataBean::class, SiteDataBean::class, TaskDataBean::class, TaskSiteDataBean::class, EventDataBean::class], version = 3)
@Database(entities = [ContrailDataBean::class, LineDataBean::class, SiteDataBean::class, TaskDataBean::class, TaskSiteDataBean::class, EventDataBean::class], version = 4)
abstract class MyDataBase : RoomDatabase() {
override fun getOpenHelper(): SupportSQLiteOpenHelper {
@@ -82,11 +83,16 @@ abstract class MyDataBase : RoomDatabase() {
}
}
FileUtils.createOrExistsDir(ROOT_PATH)
return Room.databaseBuilder(
AbsMogoApplication.getApp()!!.applicationContext, MyDataBase::class.java, ROOT_PATH+roomName
)
.addMigrations(Migration1_2(1,2))
.addMigrations(Migration2_3(2,3))
.addMigrations(Migration3_4(3,4))
.addMigrations(Migration2_4(2,4))
.fallbackToDestructiveMigration()
.build()
}
val ROOT_PATH = Environment.getExternalStorageDirectory().absolutePath + File.separator + "Mogo" + File.separator + "APP_cache" + File.separator //程序外部存储跟目录
@@ -111,4 +117,20 @@ abstract class MyDataBase : RoomDatabase() {
database.execSQL("ALTER TABLE ${TaskSiteDataBean.usedTaskDataTable} ADD COLUMN videoList TEXT");
}
}
class Migration3_4(val startVersion:Int,val endVersion:Int): Migration(startVersion,endVersion) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE ${EventDataBean.evnetDataTable} ADD COLUMN msg_id TEXT")
database.execSQL("ALTER TABLE ${EventDataBean.evnetDataTable} ADD COLUMN update_time INTEGER")
}
}
class Migration2_4(val startVersion:Int,val endVersion:Int): Migration(startVersion,endVersion) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE ${SiteDataBean.siteDataTable} ADD COLUMN videoList TEXT");
database.execSQL("ALTER TABLE ${TaskSiteDataBean.usedTaskDataTable} ADD COLUMN videoList TEXT");
database.execSQL("ALTER TABLE ${EventDataBean.evnetDataTable} ADD COLUMN msg_id TEXT")
database.execSQL("ALTER TABLE ${EventDataBean.evnetDataTable} ADD COLUMN update_time INTEGER")
}
}
}

View File

@@ -80,7 +80,13 @@ data class EventDataBean(
val eventSaveTime: Long = System.currentTimeMillis(),
@ColumnInfo(name = "update_status", typeAffinity = ColumnInfo.INTEGER)
var updateStatus:Int = 0
var updateStatus:Int = 0,
@ColumnInfo(name = "msg_id", typeAffinity = ColumnInfo.TEXT)
var msgId:String? = "",
@ColumnInfo(name = "update_time", typeAffinity = ColumnInfo.INTEGER)
var upDateTime:Long? = 0L,
) {
companion object {

View File

@@ -1,6 +1,7 @@
package com.mogo.och.weaknet.repository.db.repository
import com.mogo.och.common.module.biz.login.LoginStatusManager
import com.mogo.och.common.module.manager.cache.OchSPManager
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.och.common.module.utils.DateTimeUtil
@@ -40,6 +41,7 @@ object EventDb: IDbRepository {
event.driverId = LoginStatusManager.getLoginInfo()?.driverId?:-1
event.siteId = 0L
event.seq = 0
event.msgId = "${OchSPManager.getSn()}_${DateTimeUtil.getCurrentTimeStamp()}"
BizLoopManager.runInIoThread {
eventDataDao?.insert(event)
eventCallback?.notifySyn()
@@ -65,6 +67,7 @@ object EventDb: IDbRepository {
event.siteId = siteId
event.driverId = LoginStatusManager.getLoginInfo()?.driverId?:-1
event.seq = seq
event.msgId = "${OchSPManager.getSn()}_${DateTimeUtil.getCurrentTimeStamp()}"
BizLoopManager.runInIoThread {
eventDataDao?.insert(event)
eventCallback?.notifySyn()
@@ -90,6 +93,7 @@ object EventDb: IDbRepository {
event.driverId = LoginStatusManager.getLoginInfo()?.driverId?:-1L
event.siteId = siteId
event.seq = seq
event.msgId = "${OchSPManager.getSn()}_${DateTimeUtil.getCurrentTimeStamp()}"
BizLoopManager.runInIoThread {
eventDataDao?.insert(event)
eventCallback?.notifySyn()
@@ -108,6 +112,7 @@ object EventDb: IDbRepository {
event.driverId = LoginStatusManager.getLoginInfo()?.driverId?:-1L
event.siteId = 0L
event.seq = 0
event.msgId = "${OchSPManager.getSn()}_${DateTimeUtil.getCurrentTimeStamp()}"
BizLoopManager.runInIoThread {
eventDataDao?.insert(event)
eventCallback?.notifySyn()

View File

@@ -56,8 +56,15 @@ object TaskDb : IDbRepository {
taskDataDao.insert(*needAddDatas.toTypedArray())
}
if (needMinusDatas.isNotEmpty()) {
val needSaveTask = mutableListOf<TaskDataBean>()
// 删除任务
taskDataDao.delete(*needMinusDatas.toTypedArray())
needMinusDatas.forEach {
if(it.status==TaskDataBean.useing||it.status==TaskDataBean.used){
needSaveTask.add(it)
}
}
val failneedMinusDatas = needMinusDatas-needSaveTask
taskDataDao.delete(*failneedMinusDatas.toTypedArray())
}
}
}

View File

@@ -337,6 +337,14 @@ class WeaknetRepository : IRepository {
weakNetInterface?.reportCabinEvent(context,data,callback)
}
override fun haveRunningTask(): Boolean {
if(LineModel.currentTask==null){
return false
}else{
return true
}
}
override fun release() {
weakNetInterface = null
CallerLogger.d(TAG,"重置 weakNetInterface")

View File

@@ -7,10 +7,13 @@ import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.findViewTreeViewModelStoreOwner
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
import com.mogo.och.common.module.utils.ResourcesUtils
import com.mogo.och.common.module.utils.RxUtils
import com.mogo.och.common.module.wigets.WindowRelativeLayout
import com.mogo.och.shuttle.weaknet.R
import com.mogo.och.weaknet.repository.db.bean.LineDataBean
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.shuttle_weak_switch_biz.view.loading_biz
import kotlinx.android.synthetic.main.shuttle_weak_switch_biz.view.swtichLine
import kotlinx.android.synthetic.main.shuttle_weak_switch_biz.view.swtichTask
@@ -34,6 +37,8 @@ class SwitchBizView: WindowRelativeLayout, SwtichBizeModel.SwtichLineViewCallbac
private var viewModel: SwtichBizeModel?=null
private var queryTimeout: Disposable? = null
init {
LayoutInflater.from(context).inflate(R.layout.shuttle_weak_switch_biz, this, true)
@@ -57,9 +62,14 @@ class SwitchBizView: WindowRelativeLayout, SwtichBizeModel.SwtichLineViewCallbac
// 展示loading页面
override fun showLoadingView(){
startLoading = System.currentTimeMillis()
CallerLogger.d(TAG,"开始展示 lading 时间:${startLoading}")
loading_biz.visibility = VISIBLE
swtichLine.visibility = GONE
swtichTask.visibility = GONE
queryTimeout = RxUtils.createSubscribe(10_1000) {
OchChainLogManager.writeChainLog("Loading超时","loading 展示了10s")
viewModel?.queryRuningTask()
}
}
@@ -78,8 +88,8 @@ class SwitchBizView: WindowRelativeLayout, SwtichBizeModel.SwtichLineViewCallbac
// 展示选择任务页面
override fun showSwitchTaskInfo() {
RxUtils.disposeSubscribe(queryTimeout)
val endLoading = System.currentTimeMillis()
val dex = (100-(endLoading - startLoading)).takeIf { it>=0 }?:0
CallerLogger.d(TAG,"展示任务 lading 展示了 ${dex}毫秒")
@@ -93,6 +103,7 @@ class SwitchBizView: WindowRelativeLayout, SwtichBizeModel.SwtichLineViewCallbac
// 展示选择线路页面
override fun showSwtichLineView() {
RxUtils.disposeSubscribe(queryTimeout)
val endLoading = System.currentTimeMillis()
val dex = (100-(endLoading - startLoading)).takeIf { it>=0 }?:0
CallerLogger.d(TAG,"展示线路 lading 展示了 ${dex}毫秒")
@@ -106,6 +117,7 @@ class SwitchBizView: WindowRelativeLayout, SwtichBizeModel.SwtichLineViewCallbac
}
// 展示正在进行的任务
override fun loadRunningTask() {
RxUtils.disposeSubscribe(queryTimeout)
val endLoading = System.currentTimeMillis()
val dex = (100-(endLoading - startLoading)).takeIf { it>=0 }?:0
CallerLogger.d(TAG,"展示运行中任务 lading 展示了 ${dex}毫秒")

View File

@@ -36,6 +36,12 @@ class SwtichBizeModel : ViewModel(), IBusLinesCallback {
}
}
fun queryRuningTask(){
ThreadUtils.getIoPool().execute {
OrderModel.queryBusRoutes()
}
}
fun loadingSwitchTask(lineInfo: LineDataBean) {
d(LineModel.TAG, "loadingSwitchTask 查询线路的任务线路信息:${lineInfo}")
viewCallback?.showSwitchTaskByLineInfo(lineInfo)

View File

@@ -6,11 +6,10 @@ import androidx.appcompat.widget.AppCompatTextView
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.findViewTreeViewModelStoreOwner
import com.mogo.commons.AbsMogoApplication
import com.mogo.commons.env.ProjectUtils
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.och.shuttle.weaknet.R
import com.mogo.och.weaknet.repository.RepositoryManager
import com.mogo.och.weaknet.ui.taskrunning.TaskRunningAdapter
class WriteOffView : AppCompatTextView, WriteOffViewModel.IwriteOffViewCallback {
@@ -41,11 +40,9 @@ class WriteOffView : AppCompatTextView, WriteOffViewModel.IwriteOffViewCallback
private fun startListenerWriteOff(){
viewModel?.setWriteOffCallback(this)
visibility = VISIBLE
}
private fun stopListenerWriteOff(){
viewModel?.setWriteOffCallback(null)
visibility = GONE
if(RepositoryManager.supportWriteOff()) {
val showText =
AbsMogoApplication.getApp().getString(R.string.shuttle_write_off_count, 0)

View File

@@ -47,6 +47,7 @@
<string name="bus_dialog_cancel">取消</string>
<string name="shuttle_logout_error">请在网络良好的区域完成任务信息同步后退出</string>
<string name="shuttle_logout_error_running">请结束任务后再退出登录</string>
<string name="bus_no_task_tip">暂无任务</string>
<string name="shuttle_write_off_count">核销%1$d人</string>

View File

@@ -58,6 +58,7 @@ import com.mogo.och.common.module.map.AmapNaviToDestinationModel
import com.mogo.och.common.module.network.OchCommonServiceCallback
import com.mogo.och.common.module.utils.CoordinateCalculateRouteUtil.coordinateConverterWgsToGcjLocations
import com.mogo.och.common.module.utils.OCHThreadPoolManager
import com.mogo.och.common.module.utils.RxUtils
import com.mogo.och.common.module.voice.VoiceNotice
import com.mogo.och.data.bean.LineInfo
import com.mogo.och.data.taxi.QueryCarOrderByNoRespBean
@@ -637,6 +638,9 @@ object TaxiTaskModel {
ToastUtils.showShort("到站接口请求出现异常,请稍后重试")
DebugView.printErrorMsg("[上报ArriveSite] 到站接口请求出现异常,请稍后重试")
}
RxUtils.createSubscribe {
submitArriveSite(siteId, isArriveAtEndSite,isArrivedNearestStation)
}
}
override fun onFail(code: Int, msg: String?) {
@@ -644,6 +648,11 @@ object TaxiTaskModel {
DebugView.printErrorMsg("[上报ArriveSite] failed, code=$code, msg=$msg")
d(TAG, "code=$code msg=$msg")
ToastUtils.showShort("到站接口请求出现异常,请稍后重试,code=$code msg=$msg")
if(msg?.contains("驾舱操作过快,请稍后重试")==true){
RxUtils.createSubscribe {
submitArriveSite(siteId, isArriveAtEndSite,isArrivedNearestStation)
}
}
}
})
}

View File

@@ -216,8 +216,8 @@ ext {
//========================= autosize ======================
androidautoSize : 'com.github.JessYanCoding:AndroidAutoSize:v1.2.1',
//========================= 扫码机 ======================
serialport : 'com.mogo.support.serialport:client:1.0.0-alpha5',
//========================= 串口设备 ======================
serialport : 'com.mogo.support.device.manager:serial_port:2.2.3',
thread_opt : "com.mogo.thread.opt:lib:10.10.3",

View File

@@ -276,9 +276,9 @@ internal object V2NIdentifyDrawer: IEventDismissListener {
AiRoadMarker.aiMakers.getOrPut(id) {
AiRoadMarker().apply {
try {
val current = abs(location.gnssSpeed) * 3.6f.toInt()
val min = abs(data.speedStraightMin * 3.6f).toInt()
val max = abs(data.speedStraightMax * 3.6f).toInt()
val current = abs(location.gnssSpeed).toInt()
val min = abs(data.speedStraightMin).toInt()
val max = abs(data.speedStraightMax).toInt()
marker(Marker(id, EventTypeEnumNew.TYPE_SOCKET_ROAD_GREE_WAVE.poiType, destX, destY, 0.0, null, null, null), drawMarker = false, false)
var alertTts = ""
var alertContent = ""
@@ -521,7 +521,7 @@ internal object V2NIdentifyDrawer: IEventDismissListener {
}
private fun drawGreenWave(crossSpeed: V2nCrossSpeed) {
if (V2NCarTypeCheck.verifyCarType() && FunctionBuildConfig.v2nTotalSwitch) {
if (V2NCarTypeCheck.verifyCarType() && FunctionBuildConfig.v2nTotalSwitch && FunctionBuildConfig.v2nGreenWave) {
handler.removeMessages(MSG_WHAT_DRAW_GREEN_WAVE)
handler.sendMessage(Message.obtain(handler, MSG_WHAT_DRAW_GREEN_WAVE, crossSpeed))
}
@@ -587,4 +587,4 @@ internal object V2NIdentifyDrawer: IEventDismissListener {
// val targetIds = event.exts.split(",")
// }
}
}
}

View File

@@ -61,6 +61,7 @@ dependencies {
implementation project(':libraries:mogo-obu')
implementation project(':libraries:mogo-adas')
implementation project(':libraries:mogo-hardware-devices')
implementation rootProject.ext.dependencies.mogoaicloudtelematic
compileOnly project(':core:function-impl:mogo-core-function-map')
implementation project(':core:mogo-core-function-call')

View File

@@ -4,20 +4,20 @@ import android.content.Context
import com.alibaba.android.arouter.facade.annotation.Route
import com.mogo.eagle.core.data.constants.MogoServicePaths
import com.mogo.eagle.core.function.api.datacenter.IDataCenterProvider
import com.mogo.eagle.core.function.call.datacenter.CallerDataCenterBizListener
import com.mogo.eagle.core.function.call.datacenter.CallerDataCenterBizManager
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxManager
import com.mogo.eagle.core.function.datacenter.location.MoGoLocationDispatcher
import com.mogo.eagle.core.function.datacenter.v2x.SpeedLimitDispatcher
import com.mogo.eagle.core.function.datacenter.v2x.TrafficLightDispatcher
import com.mogo.eagle.core.function.datacenter.iot.IotInItManager
@Route(path = MogoServicePaths.PATH_DATA_CENTER_MODULE)
class DataCenterProvider: IDataCenterProvider {
class DataCenterProvider : IDataCenterProvider {
override val functionName: String
get() = "DataCenterProvider"
private var mContext:Context? = null
private var mContext: Context? = null
override fun init(context: Context?) {
MoGoLocationDispatcher.initListener()
@@ -27,6 +27,7 @@ class DataCenterProvider: IDataCenterProvider {
CallerMsgBoxManager.queryAllMessages(it)
TrafficLightDispatcher.INSTANCE.initServer(it)
SpeedLimitDispatcher.INSTANCE.initLimit(it)
IotInItManager.init()
}
}

View File

@@ -25,6 +25,7 @@ import com.mogo.eagle.core.function.call.cloud.CallerCloudListenerManager
import com.mogo.eagle.core.function.call.devatools.CallerDevaToolsManager
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager
import com.mogo.eagle.core.function.call.telematic.CallerTelematicListenerManager
import com.mogo.eagle.core.function.call.telematic.CallerTelematicManager
import com.mogo.eagle.core.function.call.v2x.CallerTrafficLightListenerManager
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
@@ -155,6 +156,42 @@ class TeleMsgHandler : IMsgHandler {
}
return
}
if (it.protocolType == TelematicConstant.DRIVE_SEAT_VIDEO_STREAM_REQ) {
try {
Log.d(TAG, "乘客屏收到司机屏转发的驾驶位视频流开关 --- 1 ---")
val content = String(it.body, Charset.defaultCharset())
Log.d(TAG, "乘客屏收到司机屏转发的驾驶位视频流开关 --- 2 ---:$content")
val data = GsonUtils.fromJson(content, Map::class.java)
val open = data["open"].toString().toInt() == 1
val playUrl = data["playUrl"]?.toString()
//TODO yangyakun
if (open) {
if (playUrl != null) {
// 1. 获取视频播放控件
val target = CallerDevaToolsManager.driveSeatVideoProvider()?.getDriveVideoView(playUrl) { event ->
}
if (target != null) {
// 2. 添加到一个ViewGroup上
// 11: 第1个1代表运营面板开关打开第2个1代表打开成功告之司机端
// 10: 第1个1代表运营面板开关打开第2个0代表打开成功告之司机端
CallerTelematicManager.sendMsgToServer(TelematicConstant.DRIVE_SEAT_VIDEO_STREAM_RSP, "11".toByteArray())
}
} else {
CallerTelematicManager.sendMsgToServer(TelematicConstant.DRIVE_SEAT_VIDEO_STREAM_RSP, "10".toByteArray())
}
} else {
//第1个0代表运营面板开关关闭第2个1代表关闭成功告之司机端; 相应的还有状态00表示关闭失败
CallerTelematicManager.sendMsgToServer(TelematicConstant.DRIVE_SEAT_VIDEO_STREAM_RSP, "01".toByteArray())
}
} catch (t: Throwable) {
t.printStackTrace()
Log.e(TAG, "乘客屏收到司机屏转发的驾驶位视频流开关--- 3 ---", t)
}
return
}
when (it.protocolType) {
MogoProtocolMsg.NORMAL_DATA -> {
try {
@@ -349,6 +386,11 @@ class TeleMsgHandler : IMsgHandler {
)
}
TelematicConstant.DRIVE_SEAT_VIDEO_STREAM_RSP -> {
// 来自客户端的响应
CallerTelematicListenerManager.invokeReceivedMsg(TelematicConstant.DRIVE_SEAT_VIDEO_STREAM_RSP, it.body)
}
else -> {
}
}

View File

@@ -0,0 +1,28 @@
package com.mogo.eagle.core.function.datacenter.iot
import com.mogo.commons.AbsMogoApplication
import com.mogo.commons.storage.SharedPrefsMgr
import com.mogo.eagle.core.function.api.cloud.IMoGoCloudListener
import com.mogo.eagle.core.function.call.cloud.CallerCloudListenerManager
import com.mogo.support.device.DevicesManager
object IotInItManager : IMoGoCloudListener {
private const val TAG = "IotInIt"
fun init() {
CallerCloudListenerManager.addListener(TAG, this)
hardwareDeviceBind(SharedPrefsMgr.getInstance().sn)
}
override fun tokenGot(token: String, sn: String) {
super.tokenGot(token, sn)
hardwareDeviceBind(sn)
}
private fun hardwareDeviceBind(sn: String) {
if (sn.isNotEmpty()) {
DevicesManager.init(AbsMogoApplication.getApp(), sn)
}
}
}

View File

@@ -57,6 +57,8 @@ import com.zhjt.mogo_core_function_devatools.badcase.consts.BadCaseConfig
import com.zhjt.mogo_core_function_devatools.binding.BindingCarManager
import com.zhjt.mogo_core_function_devatools.block.MoGoBlockProviderImpl
import com.zhjt.mogo_core_function_devatools.coldstart.ColdStartManager
import com.zhjt.mogo_core_function_devatools.driver.video.DriveSeatVideoProviderImpl
import com.mogo.eagle.core.function.api.driver.video.IDriveSeatVideoProvider
import com.zhjt.mogo_core_function_devatools.env.EnvChangeManager
import com.zhjt.mogo_core_function_devatools.exam.ExamControlManager
import com.zhjt.mogo_core_function_devatools.funcconfig.FuncConfigCenter.Companion.bizConfigCenter
@@ -125,6 +127,8 @@ class DevaToolsProvider : IDevaToolsProvider, IAppStateListener {
ARouter.getInstance().build(MogoServicePaths.PATH_MAP_ROUTE_GUIDE).navigation() as? IMapRouteProvider
}
private val driveSeatVideoProvider by lazy { DriveSeatVideoProviderImpl() }
@Volatile
private var lastCanAutopilotStatus: Int? = null
@@ -682,4 +686,8 @@ class DevaToolsProvider : IDevaToolsProvider, IAppStateListener {
override fun takeOver(@TakeOverAnnotation takeOverAnnotation: Int) {
TakeOverManager.takeOverManager.takeOver(takeOverAnnotation)
}
override fun driveSeatVideoProvider(): IDriveSeatVideoProvider {
return driveSeatVideoProvider
}
}

View File

@@ -0,0 +1,155 @@
package com.zhjt.mogo_core_function_devatools.driver.video
import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import android.view.View
import androidx.core.view.doOnAttach
import androidx.core.view.doOnDetach
import com.mogo.commons.constants.HostConst
import com.mogo.eagle.core.data.BaseResponse
import com.mogo.eagle.core.data.app.AppConfigInfo
import com.mogo.eagle.core.function.api.driver.video.IDriveSeatVideoProvider
import com.mogo.eagle.core.function.api.driver.video.IDriveSeatVideoProvider.Event
import com.mogo.eagle.core.function.api.driver.video.IDriveSeatVideoProvider.Event.Failed
import com.mogo.eagle.core.function.api.driver.video.IDriveSeatVideoProvider.Event.Loading
import com.mogo.eagle.core.function.api.driver.video.IDriveSeatVideoProvider.Event.Playing
import com.mogo.eagle.core.network.MoGoRetrofitFactory
import com.mogo.eagle.core.utilcode.util.AppStateManager
import com.tencent.liteav.basic.log.TXCLog
import com.tencent.rtmp.ITXLivePlayListener
import com.tencent.rtmp.TXLiveConstants
import com.tencent.rtmp.TXLivePlayConfig
import com.tencent.rtmp.TXLivePlayer
import com.tencent.rtmp.ui.TXCloudVideoView
import com.zhjt.mogo_core_function_devatools.driver.video.vo.VideoUrlData
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import retrofit2.http.GET
import retrofit2.http.Headers
import retrofit2.http.Query
import java.lang.ref.WeakReference
class DriveSeatVideoProviderImpl: IDriveSeatVideoProvider {
companion object {
private const val TAG = "DriveSeatVideoProvider"
}
@Volatile
private var target: WeakReference<TXCloudVideoView>? = null
@Volatile
private var timer: Job? = null
private val scope by lazy { CoroutineScope(Dispatchers.IO + SupervisorJob()) }
private var data: VideoUrlData? = null
internal interface IVideoLiveUrlApi {
@Headers("Content-Type:application/json;charset=UTF-8")
@GET("/eagleEye-mis/camera/monitor/watch/status")
suspend fun requestVideoLiveUrl(@Query(value = "numberPlate") numberPlate: String, @Query("cameraType") cameraType: Int, @Query("protocolType") protocolType: Int): BaseResponse<VideoUrlData>
}
override suspend fun requestVideoInfo(): VideoUrlData? {
val plateNumber = AppConfigInfo.plateNumber
if (TextUtils.isEmpty(plateNumber)) {
Log.e(TAG, "-- isVideoLiveUsable -- plate number is empty.")
return null
}
val resp = getApi()?.requestVideoLiveUrl(plateNumber, 2, 2) ?: return null
Log.e(TAG, "-- isVideoLiveUsable -- receive response: {code: ${resp.code}, msg: ${resp.msg}, result: ${resp.result}}")
data = resp.result
return resp.result
}
override fun getDriveVideoView(playUrl: String, playCallback: ((Event) -> Unit)?): View? {
val activity = AppStateManager.currentActivity() ?: return null
val t = target?.get()
if (t != null) {
return t
}
val x = TXCloudVideoView(activity)
Log.d(TAG, "getDriveVideoView --> $playUrl")
x.doOnAttach {
Log.d(TAG, "onAttachToWindow --> $playUrl")
val player = TXLivePlayer(activity)
player.setPlayerView(x)
player.setMute(true)
TXCLog.setLevel(4)
val config = TXLivePlayConfig()
config.setConnectRetryCount(30)
player.setConfig(config)
player.enableHardwareDecode(true)
player.startPlay(playUrl, TXLivePlayer.PLAY_TYPE_LIVE_RTMP)
player.setPlayListener(object : ITXLivePlayListener {
override fun onPlayEvent(event: Int, bundle: Bundle?) {
Log.d(TAG, "直播信息 => event: $event, playUrl: $playUrl, bundle: $bundle")
if (event == TXLiveConstants.PLAY_EVT_PLAY_LOADING) {
Log.d(TAG, "play loading...")
playCallback?.invoke(Loading)
} else if (event == TXLiveConstants.PLAY_EVT_PLAY_BEGIN) {
Log.d(TAG, "play begin...")
start()
playCallback?.invoke(Playing)
} else {
if (event < 0) {
Log.d(TAG, "play failed...$event, bundle: $bundle")
stop()
playCallback?.invoke(Failed(bundle?.toString() ?: "播放失败"))
}
}
}
override fun onNetStatus(bundle: Bundle?) {
Log.d(TAG, "直播信息 => onNetStatus -> $bundle")
}
})
x.doOnDetach {
Log.d(TAG, "-- onDetachedFromWindow ---: $playUrl")
try {
player.stopPlay(true)
stop()
} finally {
target?.clear()
}
}
}
target = WeakReference(x)
return x
}
override fun getLastData(): VideoUrlData? {
return data
}
private fun start() {
timer?.cancel()
scope.launch {
val result = requestVideoInfo()
if (result != null) {
data = result
}
delay(5000)
}.also {
timer = it
}
}
private fun stop() {
timer?.cancel()
}
private fun getApi(): IVideoLiveUrlApi? {
return MoGoRetrofitFactory.getInstanceNoCallAdapter(HostConst.getHost()).create(IVideoLiveUrlApi::class.java)
}
}

View File

@@ -81,6 +81,8 @@ dependencies {
implementation rootProject.ext.dependencies.preference_ktx
implementation rootProject.ext.dependencies.amapsearch
// 硬件管理
compileOnly project(":libraries:mogo-hardware-devices")
implementation rootProject.ext.dependencies.thread_opt
api project(':test:crashreport-apmbyte')
compileOnly project(':core:function-impl:mogo-core-function-datacenter')

View File

@@ -216,7 +216,12 @@ class StartAutoPilotStatusView @JvmOverloads constructor(
if (isAnyOneError) R.drawable.icon_no_fsm_status_bg_error
else R.drawable.icon_no_fsm_status_bg_normal
)
notifyStatus(isAnyOneError)
if (!hasFSM.get()) {
notifyStatus(isAnyOneError)
Logger.d(TAG, "--- handleWithoutFSM --- do update")
} else {
Logger.d(TAG, "--- handleWithoutFSM --- do not update")
}
}
private fun notifyStatus(isError: Boolean) {

View File

@@ -29,6 +29,7 @@ import com.iflytek.cloud.RecognizerListener
import com.iflytek.cloud.RecognizerResult
import com.iflytek.cloud.SpeechError
import com.iflytek.cloud.SpeechRecognizer
import com.mogo.commons.env.ProjectUtils
import com.mogo.commons.storage.SharedPrefsMgr
import com.mogo.eagle.core.data.app.AppConfigInfo
import com.mogo.eagle.core.data.deva.report.CategoryInfo
@@ -173,7 +174,9 @@ class FaultReasonView @JvmOverloads constructor(
iconDown?.setBounds(0, 0, iconDown.minimumWidth, iconDown.minimumHeight)
iconUp?.setBounds(0, 0, iconUp.minimumWidth, iconUp.minimumHeight)
//获取一级分类
CallerDevaToolsManager.getCategories(BadCaseConfig.tenantId, 1, 0, type, 0)
if(ProjectUtils.isSaas()){
CallerDevaToolsManager.getCategories(BadCaseConfig.tenantId, 1, 0, type, 0)
}
//弹窗展示时间
tvFaultTime.text =
millis2String(System.currentTimeMillis(), TimeUtils.getHourMinSecondFormat())
@@ -538,7 +541,9 @@ class FaultReasonView @JvmOverloads constructor(
override fun getCategoriesError(msg: String) {
super.getCategoriesError(msg)
ToastUtils.showShort("故障列表获取失败:$msg")
if(ProjectUtils.isSaas()){
ToastUtils.showShort("故障列表获取失败:$msg")
}
}
override fun onVisibilityAggregated(isVisible: Boolean) {
@@ -546,7 +551,9 @@ class FaultReasonView @JvmOverloads constructor(
if(visibility == View.VISIBLE){
CallerDevaToolsListenerManager.addListener(TAG, this)
//获取一级分类
CallerDevaToolsManager.getCategories(BadCaseConfig.tenantId, 1, 0, type, 0)
if(ProjectUtils.isSaas()){
CallerDevaToolsManager.getCategories(BadCaseConfig.tenantId, 1, 0, type, 0)
}
//弹窗展示时间
tvFaultTime.text =
millis2String(System.currentTimeMillis(), TimeUtils.getHourMinSecondFormat())

View File

@@ -191,6 +191,8 @@ class ReportTypeView @JvmOverloads constructor(
}
}
oneClickTimer?.start()
//请求一键上报故障码
CallerDevaToolsManager.getCategories(BadCaseConfig.tenantId,level,0,4,1)
}
/**
@@ -296,9 +298,11 @@ class ReportTypeView @JvmOverloads constructor(
Log.i(TAG,"onAutopilotStatistics status = "+ it.status)
if(it.status == AutopilotStatistics.AUTOPILOT_START_STATUS.FAILED){
//触发一键上报
ThreadUtils.runOnUiThread {
if(!typeSelectStatus){
showOneCLickReportView()
if(ProjectUtils.isSaas()){
ThreadUtils.runOnUiThread {
if(!typeSelectStatus){
showOneCLickReportView()
}
}
}
}

View File

@@ -31,6 +31,7 @@ import com.mogo.eagle.core.function.api.hmi.view.IViewControlListener
import com.mogo.eagle.core.function.api.hmi.view.IViewControlListener.Companion.FUNC_MODE_DEMO
import com.mogo.eagle.core.function.api.hmi.view.IViewControlListener.Companion.FUNC_MODE_RAIN
import com.mogo.eagle.core.function.api.setting.ISopSettingListener
import com.mogo.eagle.core.function.api.telematic.IReceivedMsgListener
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotControlManager
import com.mogo.eagle.core.function.call.autopilot.CallerAutoPilotStatusListenerManager
import com.mogo.eagle.core.function.call.autopilot.CallerAutopilotCarConfigListenerManager
@@ -41,6 +42,7 @@ import com.mogo.eagle.core.function.call.hmi.CallerHmiViewControlListenerManager
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager
import com.mogo.eagle.core.function.call.obu.CallerObuApiManager
import com.mogo.eagle.core.function.call.setting.CallerSopSettingManager
import com.mogo.eagle.core.function.call.telematic.CallerTelematicListenerManager
import com.mogo.eagle.core.function.call.telematic.CallerTelematicManager
import com.mogo.eagle.core.function.call.unmanned.CallerUnmannedListenerManager
import com.mogo.eagle.core.function.call.vehicle.CallerSweeperModeListenerManager
@@ -59,11 +61,13 @@ import com.mogo.eagle.core.utilcode.mogo.logger.Logger
import com.mogo.eagle.core.utilcode.mogo.vehicle.SweeperVehicleConfigUtils
import com.mogo.eagle.core.utilcode.rv.divider.CommonDividerItemDecoration
import com.mogo.eagle.core.utilcode.util.AppStateManager
import com.mogo.eagle.core.utilcode.util.GsonUtils
import com.mogo.eagle.core.utilcode.util.GsonUtils.*
import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.zhjt.mogo.adas.data.AdasConstants
import com.zhjt.mogo.adas.data.bean.AdasParam
import kotlinx.android.synthetic.main.layout_operate_panel.view.iv_operate_panel_close
import kotlinx.android.synthetic.main.layout_operate_panel_preference_widget_switch_compat.switchWidget
import kotlinx.coroutines.launch
import me.jessyan.autosize.utils.AutoSizeUtils
import mogo.telematics.pad.MessagePad
@@ -669,9 +673,10 @@ class OperatePanelLayout : LinearLayout {
}
}
class BusinessPreferenceFragmentCompat : OperatePanelDetailBase() {
class BusinessPreferenceFragmentCompat : OperatePanelDetailBase(), IReceivedMsgListener {
companion object {
private const val TAG = "BusinessPreferenceFragmentCompat"
private const val KEY_FAULT_REPORT_TIP = "fault_report_tip"
private const val KEY_LIMIT_SPEED_MARKER = "limit_speed_marker"
private const val KEY_WEATHER_EFFECT_SWITCH = "weather_effect_switch"
@@ -680,6 +685,22 @@ class OperatePanelLayout : LinearLayout {
private const val KEY_UNMANNED_DEMO_PULL_INTERVAL = "unmanned_demo_pull_interval"
private const val KEY_SWEEPER_CLOUD_CONTROL = "sweeper_cloud_control"
private const val KEY_LOOK_AROUND_360 = "look_around_360"
private const val KEY_DRIVE_SEAT_VIDEO_STREAM = "drive_seat_video_stream"
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
CallerTelematicListenerManager.addListener(TAG, this)
lifecycleScope.launchWhenResumed {
preferenceScreen.findPreferenceReal<SwitchPreferenceCompat>(KEY_DRIVE_SEAT_VIDEO_STREAM)?.also {
it.isEnabled = CallerDevaToolsManager.driveSeatVideoProvider()?.requestVideoInfo()?.livePlayUrl?.isNotEmpty() ?: false
}
}
}
override fun onDestroyView() {
super.onDestroyView()
CallerTelematicListenerManager.removeListener(TAG)
}
override fun getDefaultVal(pref: Preference): Any? {
@@ -758,6 +779,30 @@ class OperatePanelLayout : LinearLayout {
return super.onPreferenceClick(preference)
}
override fun onReceivedMsg(type: Int, byteArray: ByteArray) {
if (type == TelematicConstant.DRIVE_SEAT_VIDEO_STREAM_RSP) {
val s = String(byteArray)
clickEventAnalytics("视频流驾驶位开头-RSP->$s", false)
lifecycleScope.launchWhenResumed {
when(s) {
"01" -> {
//关闭成功
FunctionBuildConfig.isDriveSeatVideoStream = false
preferenceScreen.findPreferenceReal<SwitchPreferenceCompat>(KEY_DRIVE_SEAT_VIDEO_STREAM)?.also { changeValue(it, false) }
}
"11" -> {
//打开成功
FunctionBuildConfig.isDriveSeatVideoStream = true
preferenceScreen.findPreferenceReal<SwitchPreferenceCompat>(KEY_DRIVE_SEAT_VIDEO_STREAM)?.also { changeValue(it, true) }
}
else -> {
//关闭失败或打开失败
}
}
}
}
}
override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean {
when (preference.key) {
KEY_FAULT_REPORT_TIP -> {
@@ -848,6 +893,15 @@ class OperatePanelLayout : LinearLayout {
clickEventAnalytics("清扫云控业务", isChecked)
return true
}
KEY_DRIVE_SEAT_VIDEO_STREAM -> {
val isChecked = newValue as? Boolean ?: false
clickEventAnalytics("视频流驾驶位开关", isChecked)
val map = HashMap<String, String>()
map["open"] = if (isChecked) "1" else "0"
map["playUrl"] = CallerDevaToolsManager.driveSeatVideoProvider()?.getLastData()?.livePlayUrl ?: ""
CallerTelematicManager.sendMsgToAllClients(TelematicConstant.DRIVE_SEAT_VIDEO_STREAM_REQ, toJson(map).toByteArray())
return false
}
}
return super.onPreferenceChange(preference, newValue)
}

View File

@@ -9,6 +9,8 @@ import android.content.Intent
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Build
import android.os.Environment
import android.os.Environment.*
import android.os.Process
import android.text.Html
import android.text.TextUtils
@@ -19,6 +21,7 @@ import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.TextView
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.ListPopupWindow
import androidx.appcompat.widget.PopupMenu
import androidx.constraintlayout.widget.ConstraintLayout
@@ -115,6 +118,7 @@ import com.mogo.eagle.core.utilcode.util.AppUtils
import com.mogo.eagle.core.utilcode.util.BarUtils
import com.mogo.eagle.core.utilcode.util.CommonUtils
import com.mogo.eagle.core.utilcode.util.DeviceUtils
import com.mogo.eagle.core.utilcode.util.FileUtils
import com.mogo.eagle.core.utilcode.util.KeyboardUtils
import com.mogo.eagle.core.utilcode.util.NetworkUtils
import com.mogo.eagle.core.utilcode.util.ParseVersionUtils
@@ -132,6 +136,8 @@ import com.mogo.map.uicontroller.VisualAngleMode.MAP_STYLE_VR_ANGLE_CROSS
import com.mogo.map.uicontroller.VisualAngleMode.MAP_STYLE_VR_ANGLE_TOP
import com.mogo.map.uicontroller.VisualAngleMode.MODE_LONG_SIGHT
import com.mogo.tts.base.IMogoTTSCallback
import com.mogo.support.device.DevicesManager
import com.mogo.support.device.IBindStateChangeListener
import com.zhjt.mogo.adas.data.AdasConstants
import com.zhjt.service.chain.ChainLog
import kotlinx.android.synthetic.main.view_debug_setting.view.appVersionInfoLayout
@@ -140,6 +146,7 @@ import kotlinx.android.synthetic.main.view_debug_setting.view.btChangeEnv
import kotlinx.android.synthetic.main.view_debug_setting.view.btnAppReboot
import kotlinx.android.synthetic.main.view_debug_setting.view.btnBrakeThreshold
import kotlinx.android.synthetic.main.view_debug_setting.view.btnConnectServerIp
import kotlinx.android.synthetic.main.view_debug_setting.view.btnDeleteDB
import kotlinx.android.synthetic.main.view_debug_setting.view.btnDisconnectIpc
import kotlinx.android.synthetic.main.view_debug_setting.view.btnDrawFusion
import kotlinx.android.synthetic.main.view_debug_setting.view.btnHdVisualAdjust
@@ -272,6 +279,7 @@ import kotlinx.android.synthetic.main.view_debug_setting.view.tvDriverServerStar
import kotlinx.android.synthetic.main.view_debug_setting.view.tvGearInfo
import kotlinx.android.synthetic.main.view_debug_setting.view.tvGitBranchInfo
import kotlinx.android.synthetic.main.view_debug_setting.view.tvHDCityCode
import kotlinx.android.synthetic.main.view_debug_setting.view.tvHardwareDeviceBindState
import kotlinx.android.synthetic.main.view_debug_setting.view.tvIPCMac
import kotlinx.android.synthetic.main.view_debug_setting.view.tvIdentifyInfo
import kotlinx.android.synthetic.main.view_debug_setting.view.tvIdentifyInfoCopy
@@ -315,6 +323,8 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import mogo.telematics.pad.MessagePad
import mogo_msg.MogoReportMsg
import java.io.File
import java.io.File.*
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Timer
@@ -351,7 +361,7 @@ internal class DebugSettingView @JvmOverloads constructor(
IMoGoChassisStatesListener,
IMoGoSweeperFutianCleanSystemListener,
IMoGoObuInfoListener,
ISopSettingListener, IViewControlListener, IMoGoCloudListener {
ISopSettingListener, IViewControlListener, IMoGoCloudListener, IBindStateChangeListener {
companion object {
private const val TAG = "DebugSettingView"
@@ -474,6 +484,7 @@ internal class DebugSettingView @JvmOverloads constructor(
}
CallerObuInfoListenerManager.addListener(TAG, this)
DevicesManager.addBindStateChangeListener(TAG,this)
}
override fun onDetachedFromWindow() {
@@ -503,7 +514,7 @@ internal class DebugSettingView @JvmOverloads constructor(
CallerSopSettingManager.removeListener(TAG)
CallerHmiViewControlListenerManager.removeListener(TAG)
DevicesManager.removeBindStateChangeListener(TAG)
// 移除 业务配置监听
CallerDevaToolsFuncConfigListenerManager.unRegisterDevaToolsFuncConfigListener(
FuncBizConfig.FOUNDATION,
@@ -1323,6 +1334,40 @@ internal class DebugSettingView @JvmOverloads constructor(
}
CallerHmiManager.toggleHdMapVisualAngleAdjust(isChecked)
}
//硬件服务绑定状态以及版本
tvHardwareDeviceBindState.setOnClickListener {
val state = when (DevicesManager.getServiceBindState()) {
0 -> {
"绑定成功"
}
1 -> {
"绑定失败未安装“硬件服务”APP"
}
2 -> {
"绑定失败:没有绑定权限或找不到服务"
}
3 -> {
"服务被异常销毁"
}
else -> {
"未知"
}
}
var msg = "客户端SDK版本${DevicesManager.getSDKVersion() ?: "未知"}\n"
msg += "客户端SDK AIDL版本${DevicesManager.getSDKAIDLVersion() ?: "未知"}\n"
msg += "硬件服务端APP版本${DevicesManager.getServerVersion() ?: "未知"}\n"
msg += "硬件服务端APP AIDL版本${DevicesManager.getServerAIDLVersion() ?: ""}"
AlertDialog.Builder(context)
.setTitle("硬件服务绑定状态: $state")
.setMessage(msg)
.setPositiveButton("确定", null)
.create().show()
}
}
/**
@@ -1375,6 +1420,18 @@ internal class DebugSettingView @JvmOverloads constructor(
CallerAutoPilotControlManager.connectSpecifiedServer(ip)
}
}
btnDeleteDB.setOnClickListener {
try{
val ROOT_PATH = getExternalStorageDirectory().absolutePath + separator + "Mogo" + separator + "APP_cache" + separator
val dbDir = File(ROOT_PATH)
if(dbDir.exists()&&dbDir.isDirectory){
FileUtils.deleteFilesInDir(dbDir)
}
}catch (e:Exception){
}
}
//是否开启异常上报
tbReportWarning.isChecked = FunctionBuildConfig.isReportWarning
@@ -2707,4 +2764,31 @@ internal class DebugSettingView @JvmOverloads constructor(
private fun invokeCronetResult(json: String) {
CallerLogger.d(SceneConstant.M_HMI + "CronetNetwork", json)
}
override fun onServiceState(state: Int) {
val stateMsg = when (state) {
0 -> {
"绑定成功"
}
1 -> {
"绑定失败未安装“硬件服务”APP"
}
2 -> {
"绑定失败:没有绑定权限或找不到服务"
}
3 -> {
"服务被异常销毁"
}
else -> {
"未知"
}
}
UiThreadHandler.post {
tvHardwareDeviceBindState.text = "硬件服务绑定状态: $stateMsg"
}
}
}

View File

@@ -681,6 +681,23 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#F0F0F0" />
<TextView
android:id="@+id/tvHardwareDeviceBindState"
style="@style/DebugSettingText"
android:text="硬件服务绑定状态: 未知"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#F0F0F0" />
<TextView
android:id="@+id/tvBackgroundOperation"
style="@style/DebugSettingText"
@@ -1328,12 +1345,23 @@
</androidx.appcompat.widget.LinearLayoutCompat>
<Button
android:id="@+id/btnDeleteDB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="@dimen/dp_20"
android:text="删除业务数据库"
android:textSize="@dimen/dp_24"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/btnBrakeThreshold" />
<View
android:id="@+id/brakeThresholdDivider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#F0F0F0"
app:layout_constraintTop_toBottomOf="@id/btnBrakeThreshold" />
app:layout_constraintTop_toBottomOf="@id/btnDeleteDB" />
<Button
android:id="@+id/btnConnectServerIp"

View File

@@ -51,5 +51,12 @@
android:title="360环视"
android:persistent="false"
android:widgetLayout="@layout/layout_operate_panel_preference_widget_switch_compat" />
<SwitchPreferenceCompat
android:key="drive_seat_video_stream"
android:layout="@layout/layout_operate_panel_preference_switch_compat"
android:title="驾驶位视频流"
android:persistent="false"
android:enabled="false"
android:widgetLayout="@layout/layout_operate_panel_preference_widget_switch_compat" />
</PreferenceCategory>
</androidx.preference.PreferenceScreen>

View File

@@ -448,4 +448,11 @@ object FunctionBuildConfig {
@Volatile
@JvmField
var maxSpeedLimit: Double = 0.0
/**
* 驾驶位视频流开关是否打开-运营面板使用
*/
@Volatile
@JvmField
var isDriveSeatVideoStream: Boolean = false
}

View File

@@ -30,5 +30,16 @@ class TelematicConstant {
const val V2N_AI_ROAD_SHI_GU = 207
// -------------------- For Android Unit Test ------ END ------------
/**
* 驾驶位视频流开关-请求
*/
const val DRIVE_SEAT_VIDEO_STREAM_REQ = 208
/**
* 驾驶位视频流开关-响应
*/
const val DRIVE_SEAT_VIDEO_STREAM_RSP = 209
}
}

View File

@@ -23,6 +23,7 @@ import com.mogo.eagle.core.function.api.devatools.mofang.*
import com.mogo.eagle.core.function.api.devatools.perf.IMoGoCpuUsageProvider
import com.mogo.eagle.core.function.api.lookaround.*
import com.mogo.eagle.core.function.api.upgrade.*
import com.mogo.eagle.core.function.api.driver.video.IDriveSeatVideoProvider
/**
* 开发套件工具接口
@@ -367,4 +368,9 @@ interface IDevaToolsProvider : IProvider {
* 接管
*/
fun takeOver(@TakeOverAnnotation takeOverAnnotation: Int)
/**
* 驾驶位视频流相关业务逻辑提供者
*/
fun driveSeatVideoProvider(): IDriveSeatVideoProvider
}

View File

@@ -0,0 +1,34 @@
package com.mogo.eagle.core.function.api.driver.video
import android.view.View
import com.zhjt.mogo_core_function_devatools.driver.video.vo.VideoUrlData
interface IDriveSeatVideoProvider {
/**
* 视频直播是否可用
* @return true: 可用; false: 不可用
*/
suspend fun requestVideoInfo(): VideoUrlData?
/**
* 获取司机位视频展示控件
*/
fun getDriveVideoView(playUrl: String, playCallback: ((Event) -> Unit)? = null): View?
/**
* 获取最新的视频数据
*/
fun getLastData(): VideoUrlData?
sealed class Event {
object Loading: Event()
object Playing: Event()
data class Failed(val msg: String): Event()
}
}

View File

@@ -0,0 +1,6 @@
package com.zhjt.mogo_core_function_devatools.driver.video.vo
import androidx.annotation.Keep
@Keep data class VideoUrlData(var cameraType: Int? = null, var livePlayUrl: String? = null)

View File

@@ -28,6 +28,7 @@ import com.mogo.eagle.core.function.api.devatools.strict.*
import com.mogo.eagle.core.function.api.lookaround.*
import com.mogo.eagle.core.function.call.base.CallerBase
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.function.api.driver.video.IDriveSeatVideoProvider
object CallerDevaToolsManager {
@@ -470,4 +471,8 @@ object CallerDevaToolsManager {
fun takeOver(@TakeOverAnnotation takeOverAnnotation: Int) {
devaToolsProviderApi?.takeOver(takeOverAnnotation)
}
fun driveSeatVideoProvider(): IDriveSeatVideoProvider? {
return devaToolsProviderApi?.driveSeatVideoProvider()
}
}

View File

@@ -1,5 +1,5 @@
ext {
gradle_version = '3.5.3'
gradle_version = '3.5.4'
kotlin_plugin_version = '1.5.30'
plugin_version = '10.0.10_mogo'
service_chain_version = '5.3.14'

View File

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

View File

@@ -0,0 +1,4 @@
#### 说明
# 硬件设备管理
## 目前包含核销设备SK87R和Q350、TTS语音设备、LED屏幕

View File

@@ -0,0 +1,39 @@
plugins {
id 'com.android.library'
id 'kotlin-android'
}
android {
compileSdkVersion rootProject.ext.android.compileSdkVersion
defaultConfig {
minSdkVersion rootProject.ext.android.minSdkVersion
targetSdkVersion rootProject.ext.android.targetSdkVersion
versionCode rootProject.versionCode as int
versionName rootProject.versionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
lintOptions {
abortOnError false
}
}
dependencies {
implementation rootProject.ext.dependencies.androidxappcompat
api rootProject.ext.dependencies.serialport
}

View File

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

View File

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

View File

@@ -0,0 +1 @@
<manifest package="com.mogo.support.device"/>

View File

@@ -0,0 +1,369 @@
package com.mogo.support.device
import android.content.Context
import android.util.Log
import com.mogo.support.device.manager.DefaultDevices
import com.mogo.support.device.manager.SerialPortManager
import com.mogo.support.device.manager.SerialPortManager.SERVICE_STATE
import com.mogo.support.device.manager.bean.VerificationData
import com.mogo.support.device.manager.listener.OnBindServerListener
import com.mogo.support.device.manager.listener.OnDeviceSpeechCx830seListener
import com.mogo.support.device.manager.listener.OnDeviceVerificationListener
import com.mogo.support.serialport.common.core.Code
import com.mogo.support.serialport.common.core.Define
import com.mogo.support.serialport.common.core.Device
import com.mogo.support.serialport.common.devices.speech.cx830se.data.SwitchingValueData
import java.util.concurrent.ConcurrentHashMap
object DevicesManager {
private const val TAG = "DevicesManager"
private var serviceBindState = -1//-1未知
private val serialPortManager: SerialPortManager by lazy {
SerialPortManager() // 初始化 SerialPortManager
}
private val bindStateChangeListeners: ConcurrentHashMap<String, IBindStateChangeListener> =
ConcurrentHashMap()
private val verificationAutoListeners: ConcurrentHashMap<String, IVerificationAutoListener> =
ConcurrentHashMap()
private val speechCx830seListeners: ConcurrentHashMap<String, ISpeechCx830seListener> =
ConcurrentHashMap()
fun init(context: Context, sn: String) {
serialPortManager.bindService(context, sn, bindStateChangeListener)
}
/**
* 注册服务端APP绑定状态
*/
fun addBindStateChangeListener(tag: String, listener: IBindStateChangeListener) {
if (bindStateChangeListeners.containsKey(tag)) {
return
}
bindStateChangeListeners[tag] = listener
}
/**
* 取消注册服务端APP绑定状态
*/
fun removeBindStateChangeListener(tag: String) {
if (bindStateChangeListeners.containsKey(tag)) {
bindStateChangeListeners.remove(tag)
}
}
/**
* 注册核销设备回调接口 注册时自动连接核销设备
*/
fun addVerificationListener(tag: String, listener: IVerificationAutoListener) {
if (verificationAutoListeners.containsKey(tag)) {
return
}
verificationAutoListeners[tag] = listener
if (verificationAutoListeners.isNotEmpty()) {
if (serviceBindState == SERVICE_STATE.BIND_SUCCEED) {
serialPortManager.open(DefaultDevices.VERIFICATION, verificationListener)
}
}
}
/**
* 取消注册核销设备回调接口
*/
fun removeVerificationListener(tag: String) {
if (verificationAutoListeners.containsKey(tag)) {
verificationAutoListeners.remove(tag)
}
if (verificationAutoListeners.isEmpty()) {
}
}
/**
* 注册语音设备回调接口 注册时自动连接语音设备
*/
fun addSpeechCx830seListener(tag: String, listener: ISpeechCx830seListener) {
if (speechCx830seListeners.containsKey(tag)) {
return
}
speechCx830seListeners[tag] = listener
if (speechCx830seListeners.isNotEmpty()) {
if (serviceBindState == SERVICE_STATE.BIND_SUCCEED) {
serialPortManager.open(DefaultDevices.SPEECH_CX830SE, speechCx830seListener)
}
}
}
/**
* 取消注册语音设备回调接口
*/
fun removeSpeechCx830seListener(tag: String) {
if (speechCx830seListeners.containsKey(tag)) {
speechCx830seListeners.remove(tag)
}
}
private val bindStateChangeListener = object : OnBindServerListener() {
override fun onServiceState(serviceState: Int) {
serviceBindState = serviceState
if (bindStateChangeListeners.isNotEmpty()) {
bindStateChangeListeners.forEach {
it.value.onServiceState(serviceState)
}
}
//TODO 链路日志和埋点
// OchChainLogManager.writeChainLogScanner(
// TAG + "bindStatus",
// "绑定服务结果:serviceState:${serviceState}"
// )
when (serviceState) {
SERVICE_STATE.BIND_SUCCEED -> {
Log.d(TAG, "服务绑定成功")
if (verificationAutoListeners.isNotEmpty()) {
serialPortManager.open(DefaultDevices.VERIFICATION, verificationListener)
}
if (speechCx830seListeners.isNotEmpty()) {
serialPortManager.open(DefaultDevices.SPEECH_CX830SE, speechCx830seListener)
}
}
SERVICE_STATE.BIND_FAILURE_UNINSTALLED -> {
Log.d(TAG, "服务绑定失败未安装串口服务端APP")
}
SERVICE_STATE.BIND_FAILURE_NO_PERMISSION_NOT_FOUND -> {
Log.d(
TAG,
"服务绑定失败:没有绑定权限或找不到服务(如果是此状态,基本上安装后就可以找到,主要就是权限问题)"
)
}
SERVICE_STATE.EXCEPTION -> {
Log.d(TAG, "服务被异常销毁")
}
else -> {}
}
}
}
private val verificationListener: OnDeviceVerificationListener =
object : OnDeviceVerificationListener() {
override fun onDeviceState(
path: String?,
deviceType: Byte,
isOpen: Boolean,
message: String?
) {
if (verificationAutoListeners.isNotEmpty()) {
verificationAutoListeners.forEach {
it.value.onDeviceState(path, deviceType, isOpen, message)
}
}
}
override fun onReceive(data: VerificationData) {
if (verificationAutoListeners.isNotEmpty()) {
verificationAutoListeners.forEach {
it.value.onReceive(data)
}
}
}
}
private val speechCx830seListener: OnDeviceSpeechCx830seListener =
object : OnDeviceSpeechCx830seListener() {
override fun onSerialPortState(
path: String,
isOpen: Boolean,
throwableMessage: String?
) {
if (speechCx830seListeners.isNotEmpty()) {
speechCx830seListeners.forEach {
it.value.onOpenState(path, isOpen, throwableMessage)
}
}
// if (isOpen) {
// openBtnEnable(!serialPortManager.isOpen(selectDevice.path))
// updateUi(path, true)
// if (serialPortManager.getDeviceType(path) == DeviceType.SPEECH_CX830SE) {
// val device = serialPortManager.getOpenedSerialPort(path)
// serialPortManager.speechCx830seSendCommand(
// device,
// SpeechCommand.READ_DEVICE_ADDRESS
// )
// serialPortManager.speechCx830seSendCommand(
// device,
// SpeechCommand.READ_SWITCHING_VALUE_STATE
// )
// }
// } else {
// showOpenFailed(path)
// }
}
override fun onSpeechState(path: String, state: Int) {
if (speechCx830seListeners.isNotEmpty()) {
speechCx830seListeners.forEach {
it.value.onSpeechState(path, state)
}
}
val msg = when (state) {
Code.SUCCESS -> {
"播报内容下发成功"
}
Code.FAILED -> {
"播报内容下发失败"
}
Code.TIMEOUT -> {
"播报内容下发超时"
}
Code.SPEECH_CX830SE_SPEECH_BROADCAST_COMPLETE -> {
"播报完成"
}
else -> ""
}
Log.d(TAG, msg)
}
override fun onSwitchingValue(path: String, state: Int, data: SwitchingValueData?) {
super.onSwitchingValue(path, state, data)
if (speechCx830seListeners.isNotEmpty()) {
speechCx830seListeners.forEach {
it.value.onSwitchingValue(path, state, data)
}
}
val msg = when (state) {
Code.SUCCESS -> {
"开关量读取成功"
}
Code.TIMEOUT -> {
"开关量读取超时"
}
Code.PASSIVITY_RECEIVE -> {
"设备主动触发"
}
else -> null
}
if (!msg.isNullOrEmpty()) {
Log.d(TAG, msg)
}
}
override fun onDeviceAddress(path: String, state: Int, address: Int) {
super.onDeviceAddress(path, state, address)
if (speechCx830seListeners.isNotEmpty()) {
speechCx830seListeners.forEach {
it.value.onDeviceAddress(path, state, address)
}
}
val msg = when (state) {
Code.SUCCESS -> {
"设备地址读取成功"
}
Code.TIMEOUT -> {
"设备地址读取超时"
}
else -> null
}
if (!msg.isNullOrEmpty()) {
Log.d(TAG, msg)
}
}
override fun onCommandResponse(
path: String,
mainCommand: Int,
subcommand: Int,
state: Int
) {
super.onCommandResponse(path, mainCommand, subcommand, state)
if (speechCx830seListeners.isNotEmpty()) {
speechCx830seListeners.forEach {
it.value.onCommandResponse(path, mainCommand, subcommand, state)
}
}
// val command = SpeechCommand.getCommandBySign(mainCommand)
// var msg = ""
// if (state == Code.SUCCESS) {
// msg = "执行成功"
// } else if (state == Code.TIMEOUT) {
// msg = "执行超时"
// }
Log.i(TAG, "主命令=${mainCommand} 子命令=${subcommand} 命令结果=$state")
}
}
/**
* 语音设备(科星互联 CX-830S-E语音播报
* AIDL调用
* @param content 播报内容 打断模式下,输入 null或""可以停止语音播报
* @return 是否调用成功 调用成功(不代表命令执行成功):[Code.SUCCESS];命令未识别:[Code.COMMAND_ERROR]
*/
@Define.Code
fun speechCx830seBroadcast(content: String?): Int {
return serialPortManager.speechCx830seBroadcastSpeech(
DefaultDevices.SPEECH_CX830SE,
content
)
}
/**
* 设备是否打开
* @param device {@link DefaultDevices#SPEECH_CX830SE}
* {@link DefaultDevices#VERIFICATION}
* {@link DefaultDevices#VERIFICATION_SK87R}
* {@link DefaultDevices#VERIFICATION_Q350}
*/
fun isDeviceOpen(device: Device): Boolean {
if (DefaultDevices.VERIFICATION.equals(device)) {
return serialPortManager.isOpen(DefaultDevices.VERIFICATION_SK87R.path) || serialPortManager.isOpen(
DefaultDevices.VERIFICATION_Q350.path
)
}
return serialPortManager.isOpen(device.path)
}
/**
* 绑定状态
* -1未知 其他的状态 [SerialPortManager.SERVICE_STATE]
*/
fun getServiceBindState(): Int {
return serviceBindState
}
fun getSDKVersion(): String {
return serialPortManager.version
}
fun getSDKAIDLVersion(): String {
return serialPortManager.aidlVersion
}
fun getServerVersion(): String? {
return serialPortManager.serverVersionName
}
fun getServerAIDLVersion(): String? {
return serialPortManager.serverAidlVersion
}
}

View File

@@ -0,0 +1,6 @@
package com.mogo.support.device
//服务绑定状态接口回调
interface IBindStateChangeListener {
fun onServiceState(state: Int)
}

View File

@@ -0,0 +1,73 @@
package com.mogo.support.device;
import com.mogo.support.serialport.common.core.Define
import com.mogo.support.serialport.common.devices.speech.cx830se.data.SwitchingValueData
/**
* 语音设备(科星互联 CX-830S-E监听
*/
interface ISpeechCx830seListener {
/**
* 设备打开状态
*
* @param path 串口地址
* @param isOpen 是否打开成功
* @param throwableMessage 异常消息
*/
fun onOpenState(path: String, isOpen: Boolean, throwableMessage: String?) {}
/**
* 语音播报状态
*
* @param path 串口
* @param state 状态 语音命令下发成功:{@link Code#SUCCESS};语音命令下发失败:{@link Code#FAILED};语音命令下发超时:{@link Code#TIMEOUT};语音播报完成:{@link Code#SPEECH_CX830SE_SPEECH_BROADCAST_COMPLETE}
*/
fun onSpeechState(path: String, @Define.Code state: Int) {}
/**
* 开关量状态
* 设备主动触发开关量时 state = Code.PASSIVITY_RECEIVE
*
* @param path 串口
* @param state 状态 查询成功:{@link Code#SUCCESS};查询命令下发失败:{@link Code#FAILED};查询超时:{@link Code#TIMEOUT};设备主动触发开关量:{@link Code#PASSIVITY_RECEIVE}
* @param data 开关量数据
*/
fun onSwitchingValue(path: String, @Define.Code state: Int, data: SwitchingValueData?) {}
/**
* 设备地址
*
* @param path 串口
* @param state 查询状态 成功:{@link Code#SUCCESS};查询命令下发失败:{@link Code#FAILED};超时:{@link Code#TIMEOUT}
* @param address 设备地址 -1解析失败
*/
fun onDeviceAddress(path: String, @Define.Code state: Int, address: Int) {}
/**
* 命令下发响应
*
* @param path 串口
* @param mainCommand 命令
* @param subcommand mainCommand 中如果存在子流程则表示正在执行的子命令 目前只有存在子流程的命令有:{@link SpeechCommand#INITIALIZE}
* @param state 状态 成功:{@link Code#SUCCESS};失败:{@link Code#FAILED};超时:{@link Code#TIMEOUT};
* 当 mainCommand == {@link SpeechCommand#INITIALIZE} && subcommand == {@link SpeechCommand#UNKNOWN} 时
* state表示整体流程状态
* * 初始化开始(整体初始化流程的开始):{@link Code#SPEECH_CX830SE_INITIALIZE_START}
* * 初始化完成(整体初始化流程的完成):{@link Code#SPEECH_CX830SE_INITIALIZE_COMPLETE}
* <p>
* 当 mainCommand == {@link SpeechCommand#INITIALIZE} && subcommand != {@link SpeechCommand#UNKNOWN} 时
* state表示子命令执行状态
* * 初始化子命令开始执行(初始化流程中的子命令开始下发):{@link Code#SPEECH_CX830SE_INITIALIZE_SUBCOMMAND_START}
* * 初始化子命令成功:{@link Code#SUCCESS}
* * 初始化子命令失败:{@link Code#FAILED}
* * 初始化子命令超时:{@link Code#TIMEOUT}
*/
fun onCommandResponse(
path: String,
@Define.CommandSign mainCommand: Int,
@Define.CommandSign subcommand: Int,
@Define.Code state: Int
) {
}
}

View File

@@ -0,0 +1,16 @@
package com.mogo.support.device
import com.mogo.support.device.manager.bean.VerificationData
//核销设备数据回调
interface IVerificationAutoListener {
/**
* 设备状态
*
* @param deviceType 设备类型 [com.mogo.support.serialport.common.core.DeviceType.VERIFICATION_Q350] [com.mogo.support.serialport.common.core.DeviceType.VERIFICATION_SK87R]
* @param isOpen 是否打开
* @param message 消息
*/
fun onDeviceState(path: String?, deviceType: Byte, isOpen: Boolean, message: String?) {}
fun onReceive(data: VerificationData?)
}

View File

@@ -44,6 +44,7 @@ include ':libraries:mogo-map'
include ':libraries:mogo-adas'
include ':libraries:mogo-adas-data'
include ':libraries:mogo-obu'
include ':libraries:mogo-hardware-devices'
//include ':libraries:mapmodule'
// 语音

View File

@@ -54,7 +54,7 @@ dependencies {
implementation rootProject.ext.dependencies.androidxappcompat
implementation rootProject.ext.dependencies.arouter
implementation "com.android.tools.build:gradle:3.5.3"
implementation "com.android.tools.build:gradle:3.5.4"
kapt rootProject.ext.dependencies.aroutercompiler
if (Boolean.valueOf(USE_MAVEN_PACKAGE)) {