[fea]
[shuttle 核销全流程]
This commit is contained in:
yangyakun
2024-11-19 17:49:23 +08:00
parent e6aa52d6a4
commit 93f6e9b72d
10 changed files with 104 additions and 43 deletions

View File

@@ -24,11 +24,15 @@ class OchBluetoothGattCallback(device: BluetoothDevice) : BluetoothGattCallback(
private val waitSendData = mutableMapOf<String,UUID>()
private val maxTryCount = 6
private var currentTryCount = 0
var isConnected:Boolean by Delegates.observable(false) { _, oldValue, newValue ->
if (oldValue != newValue) {
Log.i(TAG,"链接状态发生变化")
Log.i(TAG,"链接状态发生变化${newValue}")
connectListener?.connectChangeListener()
connectListener = null
}
}
@@ -51,6 +55,9 @@ class OchBluetoothGattCallback(device: BluetoothDevice) : BluetoothGattCallback(
}
}else{
Log.i(TAG,"与[${dev}]连接出错,错误码:$status")
if(status==133){
connect()
}
}
}
@@ -210,16 +217,26 @@ class OchBluetoothGattCallback(device: BluetoothDevice) : BluetoothGattCallback(
}
}
fun connectGatt() {
fun connectGatt(code: String, businessTime: Long) {
if(isConnected){
ToastUtils.showShort("已连接成功")
writeData2UUID("1",BleManager.UUID_CHAR_WRITE)
writeData2UUID("$code,$businessTime",BleManager.UUID_CHAR_WRITE)
}else {
mBluetoothGatt = device.connectGatt(AbsMogoApplication.getApp(), false, this)
waitSendData.put("1",BleManager.UUID_CHAR_WRITE)
connect()
waitSendData["$code,$businessTime"] = BleManager.UUID_CHAR_WRITE
}
}
private fun connect(){
Log.i(TAG,"connect:第${currentTryCount}")
// 重试5次
if(currentTryCount>maxTryCount){
return
}
currentTryCount += 1
mBluetoothGatt = device.connectGatt(AbsMogoApplication.getApp(), false, this)
}
interface ConnectListener{
fun connectChangeListener(){}
fun sendDataSuccessAndCloseListener(device: BluetoothDevice)

View File

@@ -20,12 +20,12 @@ import com.mogo.och.common.module.manager.socket.lan.ILanMessageListener
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.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 com.mogo.support.device.manager.SerialPortManager
import java.util.concurrent.ConcurrentHashMap
import kotlin.properties.Delegates

View File

@@ -75,7 +75,6 @@ data class WriteOffDetialMsg(
val msg:String?,
val expiryTime: Long?=null,
val bookingTime: Long?=null,
val businessType: Int?=null,
val lineId: Long?=null,
val availableTimes: Int?=null,//剩余票数
val orderNo: String?=null,
@@ -89,9 +88,16 @@ data class WriteOffDetialMsg(
val tenantId:Long?=null
) : BaseDPMsg(DPMsgType.TYPE_WRITEOFF_INFO_DETAIL.type)
/**
* code 3001 乘客屏参数校验失败
* code 3002 司机屏校验失败原因未知
* code 99 小程序缓存丢失Android 缓存存在
*/
data class WriteOffResultMsg(
val code:Int,// 1成功 其他失败
val phone:String,// 手机号
val businessTime:Long
) : BaseDPMsg(DPMsgType.TYPE_WRITEOFF_INFO_RESULT.type)
data class WriteOffDevicesMsg(

View File

@@ -72,6 +72,7 @@ object TicketModel {
passenger.passengerSize,
passenger.phone ?: "",
passenger.ticketName?:"",
0
)
TODO("服务器端核销需要在本地报备一下 用于计算数据")
}
@@ -145,7 +146,8 @@ object TicketModel {
if (writeOffDetialMsg.code != 0) {
sendMessage2Driver(
writeOffDetialMsg.msg ?: "",
writeOffDetialMsg.phone ?: "",false
writeOffDetialMsg.phone ?: "",
writeOffDetialMsg.code
)
} else {
RepositoryManager.writeOff(writeOffDetialMsg)
@@ -173,7 +175,8 @@ object TicketModel {
writeOffSuccess(
data.ticketSize ?: 0,
data.phone ?: "",
data.ticketName ?: ""
data.ticketName ?: "",
data.businessTime?:System.currentTimeMillis(),
)
}
})
@@ -186,19 +189,20 @@ object TicketModel {
*/
private fun parseData(code:Int,msg:String,phone: String){
when (code) {
6002 -> sendMessage2Driver("同一订单核销间隔时间需大于2分钟", phone)
1009 -> sendMessage2Driver("车票所选乘车日期非今日", phone)
1005 -> sendMessage2Driver("车辆未登录、或没有任务", phone)
1006 -> sendMessage2Driver("车票路线信息与当前车辆执行任务的路线信息不符合", phone)
1008 -> sendMessage2Driver("车票剩余可用次数为0", phone)
6001 -> sendMessage2Driver("二维码已过期", phone)
1012 -> sendMessage2Driver("当前用户下单路线非当前的车辆所属公司", phone)
6002 -> sendMessage2Driver("同一订单核销间隔时间需大于2分钟", phone,6002)
1009 -> sendMessage2Driver("车票所选乘车日期非今日", phone,1009)
1005 -> sendMessage2Driver("车辆未登录、或没有任务", phone,1005)
1006 -> sendMessage2Driver("车票路线信息与当前车辆执行任务的路线信息不符合", phone,1006)
1008 -> sendMessage2Driver("车票剩余可用次数为0", phone,1008)
6001 -> sendMessage2Driver("二维码已过期", phone,6001)
1012 -> sendMessage2Driver("当前用户下单路线非当前的车辆所属公司", phone,1012)
99 -> sendMessage2Driver("已核验、请勿重新核验", phone,99)
else -> {
try {
val tempcode=msg.toInt()
parseData(tempcode,msg,phone)
}catch (e:Exception){
sendMessage2Driver(msg, phone)
sendMessage2Driver(msg, phone,3002)
}
}
}
@@ -206,10 +210,13 @@ object TicketModel {
/**
* 验票失败
* code 3001 乘客屏参数校验失败
* code 3002 司机屏校验失败原因未知
* code 99 小程序缓存丢失Android 缓存存在
*/
private fun sendMessage2Driver(message:String,phone:String,send2Source:Boolean=true){
private fun sendMessage2Driver(message:String,phone:String,code:Int){
// 发送乘客屏 通过蓝牙告知小程序
LanSocketManager.sendMsgToClient(WriteOffResultMsg(code = -1,phone = phone))
LanSocketManager.sendMsgToClient(WriteOffResultMsg(code = code, phone = phone, System.currentTimeMillis()))
val failedReason = "验票失败,${message}"
ShuttleVoiceManager.writeOffFaile(failedReason)
var tempPhone = phone
@@ -244,12 +251,19 @@ object TicketModel {
* 1、本地核销
* 2、云端核销
*/
private fun writeOffSuccess(ticketSize: Int, phone:String, ticketName:String) {
private fun writeOffSuccess(ticketSize: Int, phone:String, ticketName:String,businessTime:Long) {
// 发送乘客屏 通过蓝牙告知小程序
LanSocketManager.sendMsgToClient(WriteOffResultMsg(code = 1,phone = phone))
selectWriteOffCount()
// 发送乘客屏 通过蓝牙告知小程序 为0时是 安全员小程序核销的
if(businessTime>0) {
LanSocketManager.sendMsgToClient(
WriteOffResultMsg(
code = 0,// 00成功
phone = phone,
businessTime = businessTime
)
)
}
BizLoopManager.runInIoThread { selectWriteOffCount() }
ShuttleVoiceManager.writeOffCount(ticketSize)

View File

@@ -54,7 +54,7 @@ public interface NetInterface {
default Observable<PassengerWriteOffResponse.Result> writeOffTicket(Context context,
PassengerWriteOffRequest ticketInfo){
return Observable.just(new PassengerWriteOffResponse.Result("",0,"",0L));
return Observable.just(new PassengerWriteOffResponse.Result("",0,"",0L,0L));
}
default void queryCarExecutableTaskList(Context context , OchCommonServiceCallback<CarExecutableTaskResponse> callback){}

View File

@@ -8,6 +8,7 @@ data class PassengerWriteOffResponse(val data: Result?) : BaseData(){
val phone: String?,
val ticketSize: Int?,
val ticketName: String?,
val remainingTimes: Long?//剩余次数
val remainingTimes: Long?,//剩余次数,
val businessTime:Long?,//业务时间
)
}

View File

@@ -88,7 +88,7 @@ class WriteOffCacheRepository : IWriteOffRepository {
var siteId:Long?=null
//
// 1、校验租户id
it.tenantId?.let { tenantId->
if(LoginStatusManager.getLoginInfo()?.tenantId==tenantId){
@@ -96,7 +96,7 @@ class WriteOffCacheRepository : IWriteOffRepository {
throw DataException(1012,"当前用户下单路线非当前的车辆所属公司")
}
}
// TODO: 校验project
// 2、校验project
if(ProjectUtils.isSaas()){
if(it.pipe != WriteOffDataBean.saasXiaoChengXu){
throw DataException(1012,"当前用户下单路线非当前的车辆所属公司")
@@ -106,19 +106,19 @@ class WriteOffCacheRepository : IWriteOffRepository {
throw DataException(1012,"当前用户下单路线非当前的车辆所属公司")
}
}
// 2、校验 bus和shuttle
// 3、校验 bus和shuttle
if (LoginStatusManager.getBusInessType().name.lowercase()!=it.typeBiz) {
throw DataException(1005,"车辆未登录、或没有任务")
}
// 3 二维码1分钟失效
// 4 二维码1分钟失效
if(System.currentTimeMillis()-(it.expiryTime?:0L)>60_000){
throw DataException(6001,"二维码已过期")
}
// 4 校验乘车日期
// 5 校验乘车日期
if(!DateTimeUtil.isSameDay(System.currentTimeMillis(),it.bookingTime?:0)){
throw DataException(1009,"车票所选乘车日期非今日")
}
// 5、校验线路
// 6、校验线路
if(it.lineId==LineManager.lineInfos?.lineId){
lineId = it.lineId
}else{
@@ -126,11 +126,11 @@ class WriteOffCacheRepository : IWriteOffRepository {
}
if(AppIdentityModeUtils.isShuttle(FunctionBuildConfig.appIdentityMode)) {
// 6、校验次数
// 7、校验次数
if((it.availableTimes?:0)<=0){
throw DataException(1008,"车票剩余可用次数为0")
}
// 7、同一个订单2分钟内只能核销一次
// 8、同一个订单2分钟内只能核销一次
if (!it.orderNo.isNullOrEmpty()) {
val lastWriteOff = WriteOffDb.queryWaitUpdateEventCount(it.orderNo!!)
if(lastWriteOff!=null){
@@ -144,6 +144,7 @@ class WriteOffCacheRepository : IWriteOffRepository {
val (start, _) = LineManager.getStations()
siteId = start?.siteId?.toLong()?:0
}else if(AppIdentityModeUtils.isBus(FunctionBuildConfig.appIdentityMode)) {
// 7、校验起始站点
val (start, _) = LineManager.getStations()
if(start?.siteId?.toLong()==it.startStationId){
siteId = it.startStationId
@@ -169,7 +170,7 @@ class WriteOffCacheRepository : IWriteOffRepository {
addWrite.driverId = LoginStatusManager.getLoginInfo()?.driverId?:0
addWrite.businessTime = System.currentTimeMillis()
WriteOffDb.addOrUpdate(addWrite)
val reslut = PassengerWriteOffResponse.Result(it.phone,it.ticketSize,it.ticketName,it.availableTimes?.toLong())
val reslut = PassengerWriteOffResponse.Result(it.phone,it.ticketSize,it.ticketName,it.availableTimes?.toLong(),addWrite.businessTime)
return@flatMap Observable.just(reslut)
}
}

View File

@@ -58,16 +58,32 @@ object TicketModel : StateChangeListener {
// 收到核销结果扫描蓝牙并写会核销结果
obj?.phone?.let {phone->
var haveDevices = false
var tempRemove:BleDevItem?=null
waitConnectDev.forEach {
if(it.dev.name== getBleName(phone)){
if(it.dev.name == getBleName(phone)){
haveDevices = true
OchChainLogManager.writeChainLogWriteOff("司机端核销成功","找到设备")
it.gattcallback.connectGatt()
OchChainLogManager.writeChainLogWriteOff("司机端核销结果","${obj}_找到设备dev.name:${it.dev.name}${getBleName(phone)}")
when (obj.code) {
99 -> {
it.gattcallback.connectGatt("99",obj.businessTime)
}
0 -> {
it.gattcallback.connectGatt("00",obj.businessTime)
}
else -> {
it.gattcallback.connectGatt("01",obj.businessTime)
}
}
it.gattcallback.connectListener = connectListener
tempRemove = it
return@forEach
}
}
waitConnectDev.remove(tempRemove)
if(!haveDevices&&count<6){
RxUtils.createSubscribe {
// 没有找到设备重试5次
OchChainLogManager.writeChainLogWriteOff("司机端核销成功","2s后重试")
findDeviceConnectAndSendData(obj,count+1)
}
@@ -110,7 +126,6 @@ object TicketModel : StateChangeListener {
override fun parseData(params: MutableMap<String, String>, payload: String?) {
val expiryTime = params["expiryTime"]
val bookingTime = params["bookingTime"]
val businessType = params["businessType"]
val lineId = params["lineId"]
val availableTimes = params["availableTimes"]
val orderNo = params["orderNo"]
@@ -134,7 +149,6 @@ object TicketModel : StateChangeListener {
val writeOffDetail = WriteOffDetialMsg(0,"",
expiryTime?.toLong()?:0,
bookingTime?.toLong()?:0,
businessType?.toInt()?:0,
lineId?.toLong()?:0,
availableTimes?.toInt()?:0,
orderNo,
@@ -155,13 +169,13 @@ object TicketModel : StateChangeListener {
e.printStackTrace()
CallerLogger.d(M_BUS_P + TAG, "")
// 通知司机屏二维码错误
val writeOffDetail = WriteOffDetialMsg(code = -1, msg = "参数错误:${payload}")
val writeOffDetail = WriteOffDetialMsg(code = 3001, msg = "参数错误:${payload}")
CallerLogger.d(M_BUS_P + TAG, "sendTaskDetailsToClients = " + GsonUtils.toJson(writeOffDetail))
LanSocketManager.sendMsgToServer(writeOffDetail)
}
}else{
// 通知司机屏二维码错误
val writeOffDetail = WriteOffDetialMsg(code = -1, msg = "参数错误:${payload}")
val writeOffDetail = WriteOffDetialMsg(code = 3001, msg = "参数错误:${payload}")
CallerLogger.d(M_BUS_P + TAG, "sendTaskDetailsToClients = " + GsonUtils.toJson(writeOffDetail))
LanSocketManager.sendMsgToServer(writeOffDetail)
}
@@ -183,7 +197,7 @@ object TicketModel : StateChangeListener {
val phoneNumPre = it.substring(0, 3)
//截取电话号码后四位
val phoneNumFix = it.substring(7)
tempPhone = "mogo${phoneNumPre}$phoneNumFix"
tempPhone = "${phoneNumPre}$phoneNumFix"
}
}
return tempPhone

View File

@@ -1,5 +1,7 @@
package com.mogo.eagle.core.function.api.och
import android.view.View
/**
* 定义提供给 鹰眼底层 调用的接口
*/
@@ -8,4 +10,5 @@ interface IOchBizFunctionCall4Eagle {
* 退出登录
*/
fun logout()
fun setVideoView(target: View?)
}

View File

@@ -1,5 +1,6 @@
package com.mogo.eagle.core.function.call.och
import android.view.View
import com.mogo.eagle.core.function.api.och.IOchBizFunctionCall4Eagle
/**
@@ -24,4 +25,8 @@ object CallerOchBizFunctionCall4EagleManager : IOchBizFunctionCall4Eagle {
override fun logout() {
ochBizFunctionCall4EagleInstance?.logout()
}
override fun setVideoView(target: View?) {
ochBizFunctionCall4EagleInstance?.setVideoView(target)
}
}