diff --git a/OCH/common/common/build.gradle b/OCH/common/common/build.gradle index 6597437eaf..f4659eaf17 100644 --- a/OCH/common/common/build.gradle +++ b/OCH/common/common/build.gradle @@ -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 diff --git a/OCH/common/common/src/main/java/com/mogo/och/common/module/manager/scnner/ScannerManager.kt b/OCH/common/common/src/main/java/com/mogo/och/common/module/manager/scnner/ScannerManager.kt index 1d42c70f90..be25f16d3b 100644 --- a/OCH/common/common/src/main/java/com/mogo/och/common/module/manager/scnner/ScannerManager.kt +++ b/OCH/common/common/src/main/java/com/mogo/och/common/module/manager/scnner/ScannerManager.kt @@ -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.data.enums.EventTypeEnumNew import com.mogo.eagle.core.data.msgbox.MsgBoxBean import com.mogo.eagle.core.data.msgbox.MsgBoxType @@ -22,11 +21,11 @@ import com.mogo.och.common.module.manager.socket.lan.LanSocketManager import com.mogo.och.common.module.manager.socket.lan.bean.DPMsgType import com.mogo.och.common.module.manager.socket.lan.bean.WriteOffDetialMsg 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.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 @@ -35,7 +34,6 @@ object ScannerManager : IOchLanPassengerStatusListener { private val TAG = "ScannerManager" - private var serialPortManager = SerialPortManager() private val stateChanageListeners: ConcurrentHashMap = ConcurrentHashMap() @@ -43,8 +41,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) { @@ -72,40 +73,57 @@ 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()) { 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}") } } } @@ -113,38 +131,39 @@ 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?) { - CallerLogger.d(M_BUS_P + TAG, "$paths") - OchChainLogManager.writeChainLogScanner(TAG +"onFindSerialPort","查询串口:${paths}") - if(paths==null) { - bindStatus = BindStatus.BIND_FAILURE_NO_PERMISSION_NOT_FOUND - } - } } @@ -186,10 +205,11 @@ object ScannerManager : IOchLanPassengerStatusListener { init { //监听司机端消息 - LoginLanPassengerSocket.addListener(TAG,this) + LoginLanPassengerSocket.addListener(TAG, this) // 核销设备信息 LanSocketManager.registerSocketMessageListener(DPMsgType.TYPE_WRITEOFF_DEVICES_INFO.type,writeOfDevicefMsg) - serialPortManager.bindService(AbsMogoApplication.getApp(), onSerialPortListener)//绑定服务 + DevicesManager.addBindStateChangeListener(TAG, onSerialPortListener) + DevicesManager.addVerificationListener(TAG, onDeviceVerificationListener) } fun addStateChangeListener(tag: String, listener: StateChangeListener) { @@ -205,7 +225,7 @@ object ScannerManager : IOchLanPassengerStatusListener { override fun onDriverConnectChangeListener(isConnect: Boolean) { super.onDriverConnectChangeListener(isConnect) - if(isConnect) { + if (isConnect) { sendScannerState() } } @@ -216,17 +236,17 @@ object ScannerManager : IOchLanPassengerStatusListener { val mutableMapOf = mutableMapOf() 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}") } @@ -235,7 +255,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) @@ -254,12 +274,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) } } @@ -269,16 +289,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 -> {} } @@ -288,7 +311,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 { diff --git a/config.gradle b/config.gradle index 5ce7f621f8..e1ceac5ec3 100644 --- a/config.gradle +++ b/config.gradle @@ -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", diff --git a/core/function-impl/mogo-core-function-biz/src/main/java/com/mogo/eagle/function/biz/v2x/v2n/pnc/V2NIdentifyDrawer.kt b/core/function-impl/mogo-core-function-biz/src/main/java/com/mogo/eagle/function/biz/v2x/v2n/pnc/V2NIdentifyDrawer.kt index f6e84b1335..6f0e2e5696 100644 --- a/core/function-impl/mogo-core-function-biz/src/main/java/com/mogo/eagle/function/biz/v2x/v2n/pnc/V2NIdentifyDrawer.kt +++ b/core/function-impl/mogo-core-function-biz/src/main/java/com/mogo/eagle/function/biz/v2x/v2n/pnc/V2NIdentifyDrawer.kt @@ -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 = "" diff --git a/core/function-impl/mogo-core-function-datacenter/build.gradle b/core/function-impl/mogo-core-function-datacenter/build.gradle index 1039f768ea..0926586b53 100644 --- a/core/function-impl/mogo-core-function-datacenter/build.gradle +++ b/core/function-impl/mogo-core-function-datacenter/build.gradle @@ -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') diff --git a/core/function-impl/mogo-core-function-datacenter/src/main/java/com/mogo/eagle/core/function/DataCenterProvider.kt b/core/function-impl/mogo-core-function-datacenter/src/main/java/com/mogo/eagle/core/function/DataCenterProvider.kt index 97f447c434..df37673e6f 100644 --- a/core/function-impl/mogo-core-function-datacenter/src/main/java/com/mogo/eagle/core/function/DataCenterProvider.kt +++ b/core/function-impl/mogo-core-function-datacenter/src/main/java/com/mogo/eagle/core/function/DataCenterProvider.kt @@ -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() } } diff --git a/core/function-impl/mogo-core-function-datacenter/src/main/java/com/mogo/eagle/core/function/datacenter/autopilot/telematic/TeleMsgHandler.kt b/core/function-impl/mogo-core-function-datacenter/src/main/java/com/mogo/eagle/core/function/datacenter/autopilot/telematic/TeleMsgHandler.kt index 2c14bbc3b0..4be8d66433 100644 --- a/core/function-impl/mogo-core-function-datacenter/src/main/java/com/mogo/eagle/core/function/datacenter/autopilot/telematic/TeleMsgHandler.kt +++ b/core/function-impl/mogo-core-function-datacenter/src/main/java/com/mogo/eagle/core/function/datacenter/autopilot/telematic/TeleMsgHandler.kt @@ -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 -> { } } diff --git a/core/function-impl/mogo-core-function-datacenter/src/main/java/com/mogo/eagle/core/function/datacenter/iot/IotInItManager.kt b/core/function-impl/mogo-core-function-datacenter/src/main/java/com/mogo/eagle/core/function/datacenter/iot/IotInItManager.kt new file mode 100644 index 0000000000..33e5b3ff09 --- /dev/null +++ b/core/function-impl/mogo-core-function-datacenter/src/main/java/com/mogo/eagle/core/function/datacenter/iot/IotInItManager.kt @@ -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) + } + } +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/DevaToolsProvider.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/DevaToolsProvider.kt index b8f17f3570..cdf553419d 100644 --- a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/DevaToolsProvider.kt +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/DevaToolsProvider.kt @@ -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 + } } \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/driver/video/DriveSeatVideoProviderImpl.kt b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/driver/video/DriveSeatVideoProviderImpl.kt new file mode 100644 index 0000000000..a0e2e7c7a5 --- /dev/null +++ b/core/function-impl/mogo-core-function-devatools/src/main/java/com/zhjt/mogo_core_function_devatools/driver/video/DriveSeatVideoProviderImpl.kt @@ -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? = 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 + } + + + 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) + } +} \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-hmi/build.gradle b/core/function-impl/mogo-core-function-hmi/build.gradle index 8cd10480ce..8b9835a8e5 100644 --- a/core/function-impl/mogo-core-function-hmi/build.gradle +++ b/core/function-impl/mogo-core-function-hmi/build.gradle @@ -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') diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/bone/status/StartAutoPilotStatusView.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/bone/status/StartAutoPilotStatusView.kt index b70126a41a..ecb7e589d9 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/bone/status/StartAutoPilotStatusView.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/bone/status/StartAutoPilotStatusView.kt @@ -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) { diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/bone/tab/FaultReasonView.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/bone/tab/FaultReasonView.kt index 59247d2321..bf90a71009 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/bone/tab/FaultReasonView.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/bone/tab/FaultReasonView.kt @@ -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()) diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/bone/tab/ReportTypeView.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/bone/tab/ReportTypeView.kt index 82065a2c01..46703c5fa7 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/bone/tab/ReportTypeView.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/bone/tab/ReportTypeView.kt @@ -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() + } } } } diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/operate/OperatePanelLayout.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/operate/OperatePanelLayout.kt index 2059af003a..64c92eb7d6 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/operate/OperatePanelLayout.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/operate/OperatePanelLayout.kt @@ -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(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(KEY_DRIVE_SEAT_VIDEO_STREAM)?.also { changeValue(it, false) } + } + "11" -> { + //打开成功 + FunctionBuildConfig.isDriveSeatVideoStream = true + preferenceScreen.findPreferenceReal(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() + 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) } diff --git a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/DebugSettingView.kt b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/DebugSettingView.kt index 909a5e1e78..6dadffc3f0 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/DebugSettingView.kt +++ b/core/function-impl/mogo-core-function-hmi/src/main/java/com/mogo/eagle/core/function/hmi/ui/setting/DebugSettingView.kt @@ -21,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 @@ -135,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 @@ -276,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 @@ -357,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" @@ -480,6 +484,7 @@ internal class DebugSettingView @JvmOverloads constructor( } CallerObuInfoListenerManager.addListener(TAG, this) + DevicesManager.addBindStateChangeListener(TAG,this) } override fun onDetachedFromWindow() { @@ -509,7 +514,7 @@ internal class DebugSettingView @JvmOverloads constructor( CallerSopSettingManager.removeListener(TAG) CallerHmiViewControlListenerManager.removeListener(TAG) - + DevicesManager.removeBindStateChangeListener(TAG) // 移除 业务配置监听 CallerDevaToolsFuncConfigListenerManager.unRegisterDevaToolsFuncConfigListener( FuncBizConfig.FOUNDATION, @@ -1329,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() + } } /** @@ -2725,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" + } + } } \ No newline at end of file diff --git a/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_debug_setting.xml b/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_debug_setting.xml index cf29f61bc1..004dec529e 100644 --- a/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_debug_setting.xml +++ b/core/function-impl/mogo-core-function-hmi/src/main/res/layout/view_debug_setting.xml @@ -681,6 +681,23 @@ android:layout_width="match_parent" android:layout_height="wrap_content" /> + + + + + + + \ No newline at end of file diff --git a/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/config/FunctionBuildConfig.kt b/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/config/FunctionBuildConfig.kt index eeb2a7d44b..c971c7d358 100644 --- a/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/config/FunctionBuildConfig.kt +++ b/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/config/FunctionBuildConfig.kt @@ -448,4 +448,11 @@ object FunctionBuildConfig { @Volatile @JvmField var maxSpeedLimit: Double = 0.0 + + /** + * 驾驶位视频流开关是否打开-运营面板使用 + */ + @Volatile + @JvmField + var isDriveSeatVideoStream: Boolean = false } \ No newline at end of file diff --git a/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/multidisplay/TelematicConstant.kt b/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/multidisplay/TelematicConstant.kt index d9491b76a2..7818326490 100644 --- a/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/multidisplay/TelematicConstant.kt +++ b/core/mogo-core-data/src/main/java/com/mogo/eagle/core/data/multidisplay/TelematicConstant.kt @@ -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 } } \ No newline at end of file diff --git a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/devatools/IDevaToolsProvider.kt b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/devatools/IDevaToolsProvider.kt index 9054729d6b..9022f1d786 100644 --- a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/devatools/IDevaToolsProvider.kt +++ b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/devatools/IDevaToolsProvider.kt @@ -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 } \ No newline at end of file diff --git a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/driver/video/IDriveSeatVideoProvider.kt b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/driver/video/IDriveSeatVideoProvider.kt new file mode 100644 index 0000000000..ac4bf34c29 --- /dev/null +++ b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/driver/video/IDriveSeatVideoProvider.kt @@ -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() + } +} \ No newline at end of file diff --git a/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/driver/video/vo/VideoUrlData.kt b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/driver/video/vo/VideoUrlData.kt new file mode 100644 index 0000000000..f0540bd153 --- /dev/null +++ b/core/mogo-core-function-api/src/main/java/com/mogo/eagle/core/function/api/driver/video/vo/VideoUrlData.kt @@ -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) \ No newline at end of file diff --git a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/devatools/CallerDevaToolsManager.kt b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/devatools/CallerDevaToolsManager.kt index fc7d401cf0..5e9e91e923 100644 --- a/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/devatools/CallerDevaToolsManager.kt +++ b/core/mogo-core-function-call/src/main/java/com/mogo/eagle/core/function/call/devatools/CallerDevaToolsManager.kt @@ -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() + } } \ No newline at end of file diff --git a/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/mogo/AppIdentityModeUtils.kt b/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/mogo/AppIdentityModeUtils.kt index cd7325d559..10339673ef 100644 --- a/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/mogo/AppIdentityModeUtils.kt +++ b/core/mogo-core-utils/src/main/java/com/mogo/eagle/core/utilcode/mogo/AppIdentityModeUtils.kt @@ -1,12 +1,19 @@ package com.mogo.eagle.core.utilcode.mogo +/** + * 取值要与mis后台配置对应上 + * https://mogogo.zhidaozhixing.com/eagleEye-mis/appInfo/query/all?keyWord=&pageNum=1&pageSize=20 + */ fun AppIdentityModeUtils.getMisChannelCode(appIdentityMode: String): Int { return when { isTaxi(appIdentityMode) && isPassenger(appIdentityMode) -> 1 // 出租乘客端 isTaxi(appIdentityMode) && isDriver(appIdentityMode) -> 2 // 出租司机端 - isBus(appIdentityMode) && isPassenger(appIdentityMode) -> 3 // 公交乘客端 - isBus(appIdentityMode) && isDriver(appIdentityMode) -> 4 // 公交司机端 + isBus(appIdentityMode) && isPassenger(appIdentityMode) && isB1(appIdentityMode) -> 3 // B1公交乘客端 + isBus(appIdentityMode) && isDriver(appIdentityMode) && isB1(appIdentityMode) -> 4 // B1公交司机端 + + isBus(appIdentityMode) && isPassenger(appIdentityMode) && isB2(appIdentityMode) -> 17 // B2公交乘客端 + isBus(appIdentityMode) && isDriver(appIdentityMode) && isB2(appIdentityMode) -> 15 // B2公交司机端 isCharter(appIdentityMode) && isPassenger(appIdentityMode) -> 8 // 包车乘客端 isCharter(appIdentityMode) && isDriver(appIdentityMode) -> 9 // 包车司机端 diff --git a/gradle/ext.gradle b/gradle/ext.gradle index 25dea622b1..5576dc6070 100644 --- a/gradle/ext.gradle +++ b/gradle/ext.gradle @@ -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' diff --git a/libraries/mogo-hardware-devices/.gitignore b/libraries/mogo-hardware-devices/.gitignore new file mode 100644 index 0000000000..796b96d1c4 --- /dev/null +++ b/libraries/mogo-hardware-devices/.gitignore @@ -0,0 +1 @@ +/build diff --git a/libraries/mogo-hardware-devices/README.md b/libraries/mogo-hardware-devices/README.md new file mode 100644 index 0000000000..7fd1cc5f7d --- /dev/null +++ b/libraries/mogo-hardware-devices/README.md @@ -0,0 +1,4 @@ +#### 说明 +# 硬件设备管理 +## 目前包含:核销设备(SK87R和Q350)、TTS语音设备、LED屏幕 + diff --git a/libraries/mogo-hardware-devices/build.gradle b/libraries/mogo-hardware-devices/build.gradle new file mode 100644 index 0000000000..c8f23195be --- /dev/null +++ b/libraries/mogo-hardware-devices/build.gradle @@ -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 +} diff --git a/libraries/mogo-hardware-devices/consumer-rules.pro b/libraries/mogo-hardware-devices/consumer-rules.pro new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libraries/mogo-hardware-devices/gradle.properties b/libraries/mogo-hardware-devices/gradle.properties new file mode 100644 index 0000000000..8e93a2c225 --- /dev/null +++ b/libraries/mogo-hardware-devices/gradle.properties @@ -0,0 +1,3 @@ +GROUP=com.mogo.device +POM_ARTIFACT_ID=mogo-device +VERSION_CODE=1 \ No newline at end of file diff --git a/libraries/mogo-hardware-devices/proguard-rules.pro b/libraries/mogo-hardware-devices/proguard-rules.pro new file mode 100644 index 0000000000..f1b424510d --- /dev/null +++ b/libraries/mogo-hardware-devices/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/libraries/mogo-hardware-devices/src/main/AndroidManifest.xml b/libraries/mogo-hardware-devices/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..5761ced8af --- /dev/null +++ b/libraries/mogo-hardware-devices/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libraries/mogo-hardware-devices/src/main/java/com/mogo/support/device/DevicesManager.kt b/libraries/mogo-hardware-devices/src/main/java/com/mogo/support/device/DevicesManager.kt new file mode 100644 index 0000000000..bd2ec77ccf --- /dev/null +++ b/libraries/mogo-hardware-devices/src/main/java/com/mogo/support/device/DevicesManager.kt @@ -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 = + ConcurrentHashMap() + private val verificationAutoListeners: ConcurrentHashMap = + ConcurrentHashMap() + private val speechCx830seListeners: ConcurrentHashMap = + 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 + } +} \ No newline at end of file diff --git a/libraries/mogo-hardware-devices/src/main/java/com/mogo/support/device/IBindStateChangeListener.kt b/libraries/mogo-hardware-devices/src/main/java/com/mogo/support/device/IBindStateChangeListener.kt new file mode 100644 index 0000000000..00e53a2d59 --- /dev/null +++ b/libraries/mogo-hardware-devices/src/main/java/com/mogo/support/device/IBindStateChangeListener.kt @@ -0,0 +1,6 @@ +package com.mogo.support.device + +//服务绑定状态接口回调 +interface IBindStateChangeListener { + fun onServiceState(state: Int) +} \ No newline at end of file diff --git a/libraries/mogo-hardware-devices/src/main/java/com/mogo/support/device/ISpeechCx830seListener.kt b/libraries/mogo-hardware-devices/src/main/java/com/mogo/support/device/ISpeechCx830seListener.kt new file mode 100644 index 0000000000..710c4040d1 --- /dev/null +++ b/libraries/mogo-hardware-devices/src/main/java/com/mogo/support/device/ISpeechCx830seListener.kt @@ -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} + *

+ * 当 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 + ) { + } +} diff --git a/libraries/mogo-hardware-devices/src/main/java/com/mogo/support/device/IVerificationAutoListener.kt b/libraries/mogo-hardware-devices/src/main/java/com/mogo/support/device/IVerificationAutoListener.kt new file mode 100644 index 0000000000..ed3aaff456 --- /dev/null +++ b/libraries/mogo-hardware-devices/src/main/java/com/mogo/support/device/IVerificationAutoListener.kt @@ -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?) +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 8705e605ac..720c3a940c 100644 --- a/settings.gradle +++ b/settings.gradle @@ -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' // 语音 diff --git a/test/crashreport-noop/build.gradle b/test/crashreport-noop/build.gradle index a6ccdfcea6..ee7583553f 100644 --- a/test/crashreport-noop/build.gradle +++ b/test/crashreport-noop/build.gradle @@ -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)) {