[fea]
[二维码扫描 抽取]
This commit is contained in:
yangyakun
2025-02-18 16:46:51 +08:00
parent 5e2b645a8b
commit 6891bbcb0a
23 changed files with 449 additions and 388 deletions

View File

@@ -44,6 +44,9 @@ android {
dependencies {
testImplementation 'junit:junit:4.12'
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation rootProject.ext.dependencies.kotlinstdlib
implementation rootProject.ext.dependencies.androidxccorektx
@@ -53,10 +56,15 @@ dependencies {
implementation project(':OCH:common:common')
implementation rootProject.ext.dependencies.arouter
testImplementation project(':OCH:common:biz')
kapt rootProject.ext.dependencies.aroutercompiler
implementation project(':OCH:common:data')
implementation project(':OCH:common:bridge')
// 硬件管理
implementation project(":libraries:mogo-hardware-devices")
if (Boolean.valueOf(USE_MAVEN_PACKAGE)) {
api rootProject.ext.dependencies.mogocommons
api rootProject.ext.dependencies.mogoutils

View File

@@ -0,0 +1,241 @@
package com.mogo.och.biz.qrcode
import com.mogo.eagle.core.utilcode.mogo.Product
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_OCHCOMMON
import com.mogo.eagle.core.utilcode.util.GsonUtils
import com.mogo.eagle.core.utilcode.util.RegexUtils
import com.mogo.och.common.module.biz.scanner.QrBean
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
import com.mogo.och.common.module.manager.socket.lan.LanSocketManager
import com.mogo.och.common.module.manager.socket.lan.bean.WriteOffDetialMsg
import java.net.URLDecoder
object QrParse {
private const val TAG = "QrParse"
fun parse(payload: String?): QrBean? {
val queryParameterNames = parseQuery(payload)
return if (queryParameterNames.isNotEmpty()) {// version 1 和 version 2
parseVersion1to2(queryParameterNames)
} else {
parseVersion3ton(payload)
}
}
private fun parseVersion3ton(payload: String?): QrBean? {
payload?.let {
val split = it.split(",")
if(split.isEmpty()){
return null
}
// 业务模式+版本号
val typeAndVersion92 = split[0]
val tenantId92 = split[1]
val orderNo92 = split[2]
val uidCode = split[3]
val pipeCode = split[4]
val phoneCode = split[5]
val lineIdCode = split[6]
val expiryTimeCode = split[7]
val bookingTimeCode = split[8]
val availableTimesCode = split[9]
val ticketSize = split[10].toInt() ?:0
val base92ToBase10 = Radix91.base91ToBase10(typeAndVersion92).toString()
val bizTypeCode = base92ToBase10.substring(0,1)
val bizType = Product.getCodeFromWxQr(bizTypeCode)
val version = base92ToBase10.substring(1).toInt() + 2// 0 1 这两个版本在Android端定义 二维码从优化后开始
val tenantId = Radix91.base91ToBase10(tenantId92)
val orderNo = Radix91.base91ToBase10(orderNo92).toString()
val uid = uidCode.substring(0, 8) + "-" +
uidCode.substring(8, 12) + "-" +
uidCode.substring(12, 16) + "-" +
uidCode.substring(16, 20) + "-" +
uidCode.substring(20, 32) // 构造一个标准的 UUID 字符串
val pipe = if (pipeCode.equals("1")) {
"mogogosafety"
} else {
"ehsafety"
}
val phoneLike = Radix91.base91ToBase10(phoneCode).toString()
val phone = if (RegexUtils.isMobileExact(phoneLike)) {
phoneLike
}else{
phoneCode
}
val lineId = Radix91.base91ToBase10(lineIdCode)
val expiryTime = Radix91.base91ToBase10(expiryTimeCode)
val bookingTime = Radix91.base91ToBase10(bookingTimeCode)
val availableTimes = Radix91.base91ToBase10(availableTimesCode).toInt()
// 顺序可变部分
val shiftsId:Long
val startStationId:Long
val ticketName:String
when (Product.valueOf(bizType)) {
Product.BUS -> {
shiftsId = 0
val startStationIdCode = split[11]
startStationId = Radix91.base91ToBase10(startStationIdCode)
ticketName = ""
}
Product.SHUTTLE -> {
shiftsId = 0
val ticketNameCode = split[11]
ticketName =when (ticketNameCode) {
"0" -> {
"单站票"
}
"1" -> {
"多站票"
}
"2" -> {
"全站票"
}
"3" -> {
"通勤票"
}
else -> {
URLDecoder.decode(ticketNameCode?:"","UTF-8")
}
}
startStationId = 0
}
Product.SCHEDULED -> {
val shiftsIdCode = split[12]
shiftsId = Radix91.base91ToBase10(shiftsIdCode)
val ticketNameCode = split[11]
ticketName =when (ticketNameCode) {
"0" -> {
"单站票"
}
"1" -> {
"多站票"
}
"2" -> {
"全站票"
}
"3" -> {
"通勤票"
}
else -> {
URLDecoder.decode(ticketNameCode?:"","UTF-8")
}
}
startStationId = 0
}
else->{
shiftsId = 0
startStationId = 0
ticketName = ""
}
}
return QrBean(version, orderNo, uid, phone, bizType, pipe, expiryTime,
bookingTime, lineId, availableTimes, ticketSize, ticketName, tenantId,
shiftsId, startStationId
)
}
return null
}
/**
* 解析第一和第二版本的二维码
*/
private fun parseVersion1to2(params: MutableMap<String, String>): QrBean? {
val expiryTime = params["expiryTime"]
val bookingTime = params["bookingTime"]
val lineId = params["lineId"]
val availableTimes = params["availableTimes"]
val orderNo = params["orderNo"]
val uid = params["uid"]
val phone = params["phone"]
val ticketSize = params["ticketSize"]
val ticketName = params["ticketName"]
val type = params["type"]
val pipe = params["pipe"]
val startStationId = params["startStationId"]
val tenantId = params["tenantId"]
val shiftsId = params["shiftsId"]
if (orderNo is String && uid is String) {
var phoneNum = ""
if (phone is String) {
if (RegexUtils.isMobileExact(phone)) {
phoneNum = phone
}else{
phoneNum = phone
}
}
var tempType = 0
if (type is String) {
when (type) {
"shuttle" -> {
tempType = 11
}
"bus" -> {
tempType = 10
}
else -> {
tempType = type.toInt() ?: 0
}
}
} else {
tempType = type?.toInt() ?: 0
}
try {
val version = if (expiryTime != null && bookingTime != null && lineId != null) {
1
} else {
0
}
return QrBean(
version, orderNo, uid, phoneNum, tempType, pipe?:"",
expiryTime?.toLong() ?: 0, bookingTime?.toLong() ?: 0,
lineId?.toLong() ?: 0, availableTimes?.toInt() ?: 0,
ticketSize?.toInt() ?: 0, URLDecoder.decode(ticketName?:"","UTF-8"),
tenantId?.toLong() ?: 0, shiftsId?.toLong() ?: 0,
startStationId?.toLong() ?: 0
)
} catch (e: Exception) {
e.printStackTrace()
CallerLogger.d(M_OCHCOMMON + TAG, "")
// 通知司机屏二维码错误
val writeOffDetail = WriteOffDetialMsg(code = 3001, msg = "出示错误二维码")
OchChainLogManager.writeChainLogWriteOff("核销失败", "二维码错误+参数错误")
CallerLogger.d(
M_OCHCOMMON + TAG,
"sendTaskDetailsToClients = " + GsonUtils.toJson(writeOffDetail)
)
LanSocketManager.sendMsgToServer(writeOffDetail)
}
}
return null
}
private fun parseQuery(query: String?): MutableMap<String, String> {
val params: MutableMap<String, String> = HashMap()
if (query != null && !query.isEmpty()) {
val pairs = query.split("&".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
if(pairs.size>1) {
for (pair in pairs) {
val indexOfEquals = pair.indexOf("=")
if (indexOfEquals == -1) {
// 键无值
params[pair] = ""
} else {
val key = pair.substring(0, indexOfEquals)
val value = pair.substring(indexOfEquals + 1)
params[key] = value
}
}
}
}
return params
}
}

View File

@@ -1,4 +1,4 @@
package com.mogo.och.common.module.manager.scnner
package com.mogo.och.biz.qrcode
fun main() {

View File

@@ -1,11 +1,9 @@
package com.mogo.och.common.module.manager.scnner
package com.mogo.och.biz.qrcode
import android.net.Uri
import com.mogo.eagle.core.data.enums.EventTypeEnumNew
import com.mogo.eagle.core.data.msgbox.MsgBoxBean
import com.mogo.eagle.core.data.msgbox.MsgBoxType
import com.mogo.eagle.core.data.msgbox.V2XMsg
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxManager.saveMsgBox
import android.content.Context
import com.alibaba.android.arouter.facade.annotation.Route
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
import com.mogo.eagle.core.utilcode.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
@@ -13,10 +11,13 @@ 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.biz.scanner.BindStatus
import com.mogo.och.common.module.biz.scanner.OpenStatus
import com.mogo.och.common.module.biz.scanner.ScannerService
import com.mogo.och.common.module.biz.scanner.StateChangeListener
import com.mogo.och.common.module.constant.OchCommonConst
import com.mogo.och.common.module.manager.socket.lan.bean.WriteOffDevicesMsg
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
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
@@ -30,13 +31,14 @@ import java.util.concurrent.ConcurrentHashMap
import kotlin.properties.Delegates
object ScannerManager : IOchLanPassengerStatusListener {
@Route(path = OchCommonConst.BIZ_SCANNER)
class ScannerManager : ScannerService {
private val TAG = "ScannerManager"
private val writeOfDevicefMsg = WriteOfDevicefMsg()
private val stateChanageListeners: ConcurrentHashMap<String, StateChangeListener> =
ConcurrentHashMap()
private val stateChanageListeners: ConcurrentHashMap<String, StateChangeListener> = ConcurrentHashMap()
private var bindStatus: BindStatus by Delegates.observable(BindStatus.NOTHING) { _, oldV, newV ->
if (oldV != newV) {
@@ -170,54 +172,20 @@ object ScannerManager : IOchLanPassengerStatusListener {
}
private val writeOfDevicefMsg = object : ILanMessageListener<WriteOffDevicesMsg> {
override fun targetLan(): Class<WriteOffDevicesMsg> = WriteOffDevicesMsg::class.java
override fun onLanMsgReceived(writeOffDevicesMsg: WriteOffDevicesMsg?){
writeOffDevicesMsg?.let {
if (writeOffDevicesMsg.isConnectScanner != null) {
val reason = if (writeOffDevicesMsg.reason == null) "" else writeOffDevicesMsg.reason!!
if (writeOffDevicesMsg.isConnectScanner==true) { // 链接成功
saveMsgBox(
MsgBoxBean(
MsgBoxType.V2X,
V2XMsg(
EventTypeEnumNew.TYPE_DEVICE_STATUS_NORMAL.poiType,
reason,
EventTypeEnumNew.TYPE_DEVICE_STATUS_NORMAL.tts,
""
)
)
)
} else { // 核验失败
saveMsgBox(
MsgBoxBean(
MsgBoxType.V2X,
V2XMsg(
EventTypeEnumNew.TYPE_DEVICE_STATUS_ABNORMAL.poiType,
reason,
EventTypeEnumNew.TYPE_DEVICE_STATUS_ABNORMAL.tts,
""
)
)
)
}
}
private val connect2DriverListener = object :IOchLanPassengerStatusListener{
override fun onDriverConnectChangeListener(isConnect: Boolean) {
if (isConnect) {
sendScannerState()
}
}
}
init {
//监听司机端消息
LoginLanPassengerSocket.addListener(TAG, this)
// 核销设备信息
LanSocketManager.registerSocketMessageListener(DPMsgType.TYPE_WRITEOFF_DEVICES_INFO.type,writeOfDevicefMsg)
// 绑定状态
DevicesManager.addBindStateChangeListener(TAG, onSerialPortListener)
// 核销信息
DevicesManager.addVerificationListener(TAG, onDeviceVerificationListener)
override fun init(context: Context?) {
}
fun addStateChangeListener(tag: String, listener: StateChangeListener) {
override fun addStateChangeListener(tag: String, listener: StateChangeListener) {
if (stateChanageListeners.containsKey(tag)) {
return
}
@@ -225,18 +193,43 @@ object ScannerManager : IOchLanPassengerStatusListener {
listener.stateChange(bindStatus, openStatus)
}
fun removeListener(tag:String){
override fun removeListener(tag:String){
stateChanageListeners.remove(tag)
}
override fun onDriverConnectChangeListener(isConnect: Boolean) {
if (isConnect) {
sendScannerState()
override fun load(){
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) {
// 核销设备信息
LanSocketManager.registerSocketMessageListener(DPMsgType.TYPE_WRITEOFF_DEVICES_INFO.type, writeOfDevicefMsg)
}else{
//监听和司机端连接消息
LoginLanPassengerSocket.addListener(TAG, connect2DriverListener)
// 绑定状态
DevicesManager.addBindStateChangeListener(TAG, onSerialPortListener)
// 核销信息
DevicesManager.addVerificationListener(TAG, onDeviceVerificationListener)
}
}
override fun release(){
if (AppIdentityModeUtils.isDriver(FunctionBuildConfig.appIdentityMode)) {
LanSocketManager.unRegisterSocketMessageListener(
DPMsgType.TYPE_WRITEOFF_DEVICES_INFO.type,
writeOfDevicefMsg
)
}else{
//监听司机端消息
LoginLanPassengerSocket.removeListener(TAG)
// 绑定状态
DevicesManager.removeBindStateChangeListener(TAG)
// 核销信息
DevicesManager.removeVerificationListener(TAG)
}
}
fun parseParams(payload: String?) {
val qrBean = QrBean.parse(payload)
val qrBean = QrParse.parse(payload)
if (qrBean!=null) {
if (stateChanageListeners.size > 0) {
stateChanageListeners.forEach {
@@ -305,16 +298,4 @@ object ScannerManager : IOchLanPassengerStatusListener {
}
}
enum class BindStatus {
BIND_SUCCEED,
BIND_FAILURE_UNINSTALLED,
BIND_FAILURE_NO_PERMISSION_NOT_FOUND,
EXCEPTION,
NOTHING
}
enum class OpenStatus {
Open, Unopen
}

View File

@@ -0,0 +1,45 @@
package com.mogo.och.biz.qrcode
import com.mogo.eagle.core.data.enums.EventTypeEnumNew
import com.mogo.eagle.core.data.msgbox.MsgBoxBean
import com.mogo.eagle.core.data.msgbox.MsgBoxType
import com.mogo.eagle.core.data.msgbox.V2XMsg
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxManager.saveMsgBox
import com.mogo.och.common.module.manager.socket.lan.ILanMessageListener
import com.mogo.och.common.module.manager.socket.lan.bean.WriteOffDevicesMsg
class WriteOfDevicefMsg : ILanMessageListener<WriteOffDevicesMsg> {
override fun targetLan(): Class<WriteOffDevicesMsg> = WriteOffDevicesMsg::class.java
override fun onLanMsgReceived(writeOffDevicesMsg: WriteOffDevicesMsg?){
writeOffDevicesMsg?.let {
if (it.isConnectScanner != null) {
val reason = it.reason ?: ""
if (it.isConnectScanner==true) { // 链接成功
saveMsgBox(
MsgBoxBean(
MsgBoxType.V2X,
V2XMsg(
EventTypeEnumNew.TYPE_DEVICE_STATUS_NORMAL.poiType,
reason,
EventTypeEnumNew.TYPE_DEVICE_STATUS_NORMAL.tts,
""
)
)
)
} else { // 核验失败
saveMsgBox(
MsgBoxBean(
MsgBoxType.V2X,
V2XMsg(
EventTypeEnumNew.TYPE_DEVICE_STATUS_ABNORMAL.poiType,
reason,
EventTypeEnumNew.TYPE_DEVICE_STATUS_ABNORMAL.tts,
""
)
)
)
}
}
}
}
}

View File

@@ -1,7 +1,6 @@
package com.mogo.och.common.module
package com.mogo.och.biz.qrcode
import com.mogo.och.common.module.manager.scnner.QrBean
import com.mogo.och.common.module.manager.scnner.Radix91
import com.mogo.och.common.module.biz.scanner.QrBean
import org.junit.Test
/**
@@ -36,13 +35,13 @@ open class QrUnitTest {
val ticketName = "%E5%85%A8%E7%AB%99%E7%A5%A8"
val shiftsId = 3422L
val shiftsIdEncode = Radix91.decimalToBase91(shiftsId)
val startStationId = 3466L
val startStationIdEncode = Radix91.decimalToBase91(startStationId)
// val startStationId = 3466L
// val startStationIdEncode = Radix91.decimalToBase91(startStationId)
val qrInfo2 = "$typeVersion,$tenantldEncode,$orderNoEncode,$uid,$pipe,$phoneEncode,$lineIdEncode,$expiryTimeEncode,$bookingTimeEncode,$availableTimes,$ticketSize,$ticketName,$shiftsIdEncode,$startStationIdEncode"
val qrInfo2 = "$typeVersion,$tenantldEncode,$orderNoEncode,$uid,$pipe,$phoneEncode,$lineIdEncode,$expiryTimeEncode,$bookingTimeEncode,$availableTimes,$ticketSize,$ticketName,$shiftsIdEncode"
println(qrInfo2)
val qrBean2 = QrBean.parse(qrInfo2)
val qrBean2 = QrParse.parse(qrInfo2)
println("${type}_${qrBean2?.bizType}")
println("${version}_${qrBean2?.version}")
@@ -58,15 +57,15 @@ open class QrUnitTest {
println("${ticketSize}_${qrBean2?.ticketSize}")
println("${ticketName}_${qrBean2?.ticketName}")
println("${shiftsId}_${qrBean2?.shiftsId}")
println("${startStationId}_${qrBean2?.startStationId}")
//println("${startStationId}_${qrBean2?.startStationId}")
val qrInfo1 = "orderNo=1871744897569038336&uid=828aa91f-49a1-f9b3-4526-f58acda9df60&pipe=mogogosafety&phone=houyanli&lineId=134&expiryTime=1735094149070&bookingTime=1735056000000&tenantId=337197925358633123&availableTimes=1&ticketSize=1&ticketName=%E9%80%9A%E5%8B%A4%E7%A5%A8%E3%81%AE&type=14&shiftsId=4249"
val qrBean1 = QrBean.parse(qrInfo1)
val qrBean1 = QrParse.parse(qrInfo1)
println(qrBean1)
val qrInfo0 = "orderNo=1878747772463988736&uid=4fda39cf-27a7-b49e-52ec-c566c3bc2fb8&type=shuttle&pipe=ehsafety&phone=13534015919"
val qrBean0 = QrBean.parse(qrInfo0)
val qrBean0 = QrParse.parse(qrInfo0)
println(qrBean0)
}

View File

@@ -64,9 +64,6 @@ dependencies {
implementation rootProject.ext.dependencies.amapnavi3dmap
implementation rootProject.ext.dependencies.rxandroid
// 硬件管理
implementation project(":libraries:mogo-hardware-devices")
implementation rootProject.ext.dependencies.arouter
kapt rootProject.ext.dependencies.aroutercompiler

View File

@@ -38,7 +38,6 @@ import com.mogo.och.common.module.biz.birdge.BridgeManager
import com.mogo.och.common.module.biz.order.OrderManager
import com.mogo.och.common.module.debug.location.MogoLocationExit
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.och.common.module.manager.scnner.ScannerManager
//import com.mogo.och.bridge.distance.TrajectoryAndDistanceManager
//import com.mogo.och.bridge.utils.CoordinateCalculateRouteUtil
//import com.mogo.och.bridge.utils.CoordinateCalculateRouteUtil
@@ -128,7 +127,7 @@ object DebugDataDispatch {
scanner -> {
val qrInfo = intent.getStringExtra("qrInfo")
BizLoopManager.runInIoThread{
ScannerManager.parseParams("orderNo=1871744897569038336&uid=828aa91f-49a1-f9b3-4526-f58acda9df60&pipe=mogogosafety&phone=houyanli&lineId=134&expiryTime=1735094149070&bookingTime=1735056000000&tenantId=337197925358633123&availableTimes=1&ticketSize=1&ticketName=%E9%80%9A%E5%8B%A4%E7%A5%A8%E3%81%AE&type=14&shiftsId=4249")
//ScannerManager.parseParams("orderNo=1871744897569038336&uid=828aa91f-49a1-f9b3-4526-f58acda9df60&pipe=mogogosafety&phone=houyanli&lineId=134&expiryTime=1735094149070&bookingTime=1735056000000&tenantId=337197925358633123&availableTimes=1&ticketSize=1&ticketName=%E9%80%9A%E5%8B%A4%E7%A5%A8%E3%81%AE&type=14&shiftsId=4249")
}
}
globalPathMock -> {

View File

@@ -14,8 +14,6 @@ import com.mogo.och.common.module.manager.socket.lan.LanSocketManager
import com.mogo.och.common.module.manager.socket.lan.bean.BaseDPMsg
import com.mogo.och.common.module.manager.socket.lan.bean.DPMsgType
import com.mogo.och.common.module.manager.socket.lan.bean.EnvCheck
import com.mogo.och.common.module.manager.socket.lan.bean.EnvType
import com.mogo.och.common.module.manager.socket.lan.bean.ProjectType
import com.mogo.och.common.module.utils.CallerBase
import kotlin.properties.Delegates

View File

@@ -0,0 +1,24 @@
package com.mogo.och.common.module.biz.scanner
data class QrBean(
// 二维码版本
val version: Int,
// 第一个版本
val orderNo: String = "", // 订单Id
val uid: String = "",// 服务器端唯一码
val phone: String = "",// 手机号码
val bizType: Int = 0,//
val pipe: String = "",// 渠道ehsafety mogogosafety
// 第二个版本
val expiryTime: Long = 0, // 二维码有效期
val bookingTime: Long = 0,// 预定时间
val lineId: Long = 0, // 线路id
val availableTimes: Int = 0,//总票数
val ticketSize: Int = 0,// 票上几个人
val ticketName: String = "",// 票的名称
val tenantId: Long = 0,// 租户id
val shiftsId: Long = 0,// 班车业务 任务id
val startStationId: Long = 0,// bus业务使用 开始站点名称
)

View File

@@ -0,0 +1,13 @@
package com.mogo.och.common.module.biz.scanner
enum class BindStatus {
BIND_SUCCEED,
BIND_FAILURE_UNINSTALLED,
BIND_FAILURE_NO_PERMISSION_NOT_FOUND,
EXCEPTION,
NOTHING
}
enum class OpenStatus {
Open, Unopen
}

View File

@@ -0,0 +1,29 @@
package com.mogo.och.common.module.biz.scanner
import com.alibaba.android.arouter.launcher.ARouter
import com.mogo.och.common.module.constant.OchCommonConst
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
object ScannerManager {
private var scannerService: ScannerService? =
ARouter.getInstance().build(OchCommonConst.BIZ_SCANNER).navigation() as ScannerService
fun load(){
OchChainLogManager.writeChainLogInit("初始化信息","初始化扫描器")
scannerService?.load()
}
fun release(){
OchChainLogManager.writeChainLogInit("释放信息","释放扫描器")
scannerService?.release()
}
fun addStateChangeListener(tag: String, listener: StateChangeListener) {
scannerService?.addStateChangeListener(tag,listener)
}
fun removeListener(tag:String){
scannerService?.removeListener(tag)
}
}

View File

@@ -0,0 +1,11 @@
package com.mogo.och.common.module.biz.scanner
import com.alibaba.android.arouter.facade.template.IProvider
interface ScannerService : IProvider {
fun addStateChangeListener(tag: String, listener: StateChangeListener) {}
fun removeListener(tag:String){}
fun load(){}
fun release(){}
}

View File

@@ -1,4 +1,4 @@
package com.mogo.och.common.module.manager.scnner
package com.mogo.och.common.module.biz.scanner
import android.content.Context
import android.util.AttributeSet

View File

@@ -1,4 +1,4 @@
package com.mogo.och.common.module.manager.scnner
package com.mogo.och.common.module.biz.scanner
interface StateChangeListener {
fun stateChange(newBindValue: BindStatus, newOpentValue: OpenStatus){}

View File

@@ -30,6 +30,7 @@ class OchCommonConst {
const val BIZ_LOGIN = "/ochbiz/common/login"
const val BIZ_SKIN = "/ochbiz/common/skin"
const val BIZ_SCANNER = "/ochbiz/common/scanner"
const val BIZ_TIME = "/ochbiz/common/time"
const val BIZ_OFFLINE = "/offlinedriver/offlinedata"
const val BIZ_Bridge = "/birdge/bridge"

View File

@@ -1,227 +0,0 @@
package com.mogo.och.common.module.manager.scnner
import com.mogo.eagle.core.utilcode.mogo.Product
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_OCHCOMMON
import com.mogo.eagle.core.utilcode.util.GsonUtils
import com.mogo.eagle.core.utilcode.util.RegexUtils
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
import com.mogo.och.common.module.manager.socket.lan.LanSocketManager
import com.mogo.och.common.module.manager.socket.lan.bean.WriteOffDetialMsg
import java.net.URLDecoder
data class QrBean(
// 二维码版本
val version: Int,
// 第一个版本
val orderNo: String = "", // 订单Id
val uid: String = "",// 服务器端唯一码
val phone: String = "",// 手机号码
val bizType: Int = 0,//
val pipe: String = "",// 渠道ehsafety mogogosafety
// 第二个版本
val expiryTime: Long = 0, // 二维码有效期
val bookingTime: Long = 0,// 预定时间
val lineId: Long = 0, // 线路id
val availableTimes: Int = 0,//总票数
val ticketSize: Int = 0,// 票上几个人
val ticketName: String = "",// 票的名称
val tenantId: Long = 0,// 租户id
val shiftsId: Long = 0,// 班车业务 任务id
val startStationId: Long = 0,// bus业务使用 开始站点名称
) {
companion object {
const val TAG = "QrBean"
fun parse(payload: String?): QrBean? {
val queryParameterNames = parseQuery(payload)
return if (queryParameterNames.isNotEmpty()) {// version 1 和 version 2
parseVersion1to2(queryParameterNames)
} else {
parseVersion3ton(payload)
}
}
private fun parseVersion3ton(payload: String?):QrBean? {
payload?.let {
val split = it.split(",")
if(split.isEmpty()){
return null
}
// 业务模式+版本号
val typeAndVersion92 = split[0]
val tenantId92 = split[1]
val orderNo92 = split[2]
val uidCode = split[3]
val pipeCode = split[4]
val phoneCode = split[5]
val lineIdCode = split[6]
val expiryTimeCode = split[7]
val bookingTimeCode = split[8]
val availableTimesCode = split[9]
val ticketSize = split[10].toInt() ?:0
val ticketNameCode = split[11]
val shiftsIdCode = split[12]
val startStationIdCode = split[13]
val base92ToBase10 = Radix91.base91ToBase10(typeAndVersion92).toString()
val bizTypeCode = base92ToBase10.substring(0,1)
val bizType = Product.getCodeFromWxQr(bizTypeCode)
val version = base92ToBase10.substring(1).toInt() + 2// 0 1 这两个版本在Android端定义 二维码从优化后开始
val tenantId = Radix91.base91ToBase10(tenantId92)
val orderNo = Radix91.base91ToBase10(orderNo92).toString()
val uid = uidCode.substring(0, 8) + "-" +
uidCode.substring(8, 12) + "-" +
uidCode.substring(12, 16) + "-" +
uidCode.substring(16, 20) + "-" +
uidCode.substring(20, 32) // 构造一个标准的 UUID 字符串
val pipe = if (pipeCode.equals("1")) {
"mogogosafety"
} else {
"ehsafety"
}
val phoneLike = Radix91.base91ToBase10(phoneCode).toString()
val phone = if (RegexUtils.isMobileExact(phoneLike)) {
phoneLike
}else{
phoneCode
}
val lineId = Radix91.base91ToBase10(lineIdCode)
val expiryTime = Radix91.base91ToBase10(expiryTimeCode)
val bookingTime = Radix91.base91ToBase10(bookingTimeCode)
val availableTimes = Radix91.base91ToBase10(availableTimesCode).toInt()
val ticketName =when (ticketNameCode) {
"0" -> {
"单站票"
}
"1" -> {
"多站票"
}
"2" -> {
"全站票"
}
"3" -> {
"通勤票"
}
else -> {
URLDecoder.decode(ticketNameCode?:"","UTF-8")
}
}
val shiftsId = Radix91.base91ToBase10(shiftsIdCode)
val startStationId = Radix91.base91ToBase10(startStationIdCode)
return QrBean(version, orderNo, uid, phone, bizType, pipe, expiryTime,
bookingTime, lineId, availableTimes, ticketSize, ticketName, tenantId,
shiftsId, startStationId
)
}
return null
}
/**
* 解析第一和第二版本的二维码
*/
private fun parseVersion1to2(params: MutableMap<String, String>): QrBean? {
val expiryTime = params["expiryTime"]
val bookingTime = params["bookingTime"]
val lineId = params["lineId"]
val availableTimes = params["availableTimes"]
val orderNo = params["orderNo"]
val uid = params["uid"]
val phone = params["phone"]
val ticketSize = params["ticketSize"]
val ticketName = params["ticketName"]
val type = params["type"]
val pipe = params["pipe"]
val startStationId = params["startStationId"]
val tenantId = params["tenantId"]
val shiftsId = params["shiftsId"]
if (orderNo is String && uid is String) {
var phoneNum = ""
if (phone is String) {
if (RegexUtils.isMobileExact(phone)) {
phoneNum = phone
}else{
phoneNum = phone
}
}
var tempType = 0
if (type is String) {
when (type) {
"shuttle" -> {
tempType = 11
}
"bus" -> {
tempType = 10
}
else -> {
tempType = type.toInt() ?: 0
}
}
} else {
tempType = type?.toInt() ?: 0
}
try {
val version = if (expiryTime != null && bookingTime != null && lineId != null) {
1
} else {
0
}
return QrBean(
version, orderNo, uid, phoneNum, tempType, pipe?:"",
expiryTime?.toLong() ?: 0, bookingTime?.toLong() ?: 0,
lineId?.toLong() ?: 0, availableTimes?.toInt() ?: 0,
ticketSize?.toInt() ?: 0, URLDecoder.decode(ticketName?:"","UTF-8"),
tenantId?.toLong() ?: 0, shiftsId?.toLong() ?: 0,
startStationId?.toLong() ?: 0
)
} catch (e: Exception) {
e.printStackTrace()
CallerLogger.d(M_OCHCOMMON + TAG, "")
// 通知司机屏二维码错误
val writeOffDetail = WriteOffDetialMsg(code = 3001, msg = "出示错误二维码")
OchChainLogManager.writeChainLogWriteOff("核销失败", "二维码错误+参数错误")
CallerLogger.d(
M_OCHCOMMON + TAG,
"sendTaskDetailsToClients = " + GsonUtils.toJson(writeOffDetail)
)
LanSocketManager.sendMsgToServer(writeOffDetail)
}
}
return null
}
private fun parseQuery(query: String?): MutableMap<String, String> {
val params: MutableMap<String, String> = HashMap()
if (query != null && !query.isEmpty()) {
val pairs = query.split("&".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
if(pairs.size>1) {
for (pair in pairs) {
val indexOfEquals = pair.indexOf("=")
if (indexOfEquals == -1) {
// 键无值
params[pair] = ""
} else {
val key = pair.substring(0, indexOfEquals)
val value = pair.substring(indexOfEquals + 1)
params[key] = value
}
}
}
}
return params
}
}
}

View File

@@ -1,61 +0,0 @@
package com.mogo.och.common.module.manager.scnner
import com.mogo.eagle.core.data.enums.EventTypeEnumNew
import com.mogo.eagle.core.data.msgbox.MsgBoxBean
import com.mogo.eagle.core.data.msgbox.MsgBoxType
import com.mogo.eagle.core.data.msgbox.V2XMsg
import com.mogo.eagle.core.function.call.msgbox.CallerMsgBoxManager.saveMsgBox
import com.mogo.och.common.module.manager.socket.lan.bean.WriteOffDevicesMsg
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
object ScannerClientManager {
private val TAG = "ScannerClientManager"
private val writeOfDevicefMsg = object : ILanMessageListener<WriteOffDevicesMsg> {
override fun targetLan(): Class<WriteOffDevicesMsg> = WriteOffDevicesMsg::class.java
override fun onLanMsgReceived(writeOffDevicesMsg: WriteOffDevicesMsg?){
writeOffDevicesMsg?.let {
if (it.isConnectScanner != null) {
val reason = it.reason ?: ""
if (it.isConnectScanner==true) { // 链接成功
saveMsgBox(
MsgBoxBean(
MsgBoxType.V2X,
V2XMsg(
EventTypeEnumNew.TYPE_DEVICE_STATUS_NORMAL.poiType,
reason,
EventTypeEnumNew.TYPE_DEVICE_STATUS_NORMAL.tts,
""
)
)
)
} else { // 核验失败
saveMsgBox(
MsgBoxBean(
MsgBoxType.V2X,
V2XMsg(
EventTypeEnumNew.TYPE_DEVICE_STATUS_ABNORMAL.poiType,
reason,
EventTypeEnumNew.TYPE_DEVICE_STATUS_ABNORMAL.tts,
""
)
)
)
}
}
}
}
}
fun load(){
// 核销设备信息
LanSocketManager.registerSocketMessageListener(DPMsgType.TYPE_WRITEOFF_DEVICES_INFO.type,writeOfDevicefMsg)
}
fun release(){
LanSocketManager.unRegisterSocketMessageListener(DPMsgType.TYPE_WRITEOFF_DEVICES_INFO.type,writeOfDevicefMsg)
}
}

View File

@@ -6,14 +6,13 @@ import androidx.fragment.app.Fragment
import com.alibaba.android.arouter.facade.annotation.Route
import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger.d
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_BUS
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.och.common.module.constant.OchCommonConst
import com.mogo.och.common.module.biz.provider.CommonServiceImpl
import com.mogo.och.bridge.autopilot.autopilot.OchAutopilotAnalytics
import com.mogo.och.bridge.ui.autopilot.AutopilotState
import com.mogo.och.common.module.manager.scnner.ScannerClientManager
import com.mogo.och.common.module.biz.scanner.ScannerManager
import com.mogo.och.weaknet.repository.db.repository.EventDb
import com.mogo.och.weaknet.repository.db.repository.LineDb
import com.mogo.och.weaknet.repository.db.repository.TaskDb
@@ -56,7 +55,7 @@ class ShuttleDriverProvider : CommonServiceImpl() {
}
OchAutopilotAnalytics.ochEventKey = BusAnalyticsManager
LineModel.init()
ScannerClientManager.load()
ScannerManager.load()
BusTrajectoryManager.load()
return busFragment!!
}
@@ -66,7 +65,7 @@ class ShuttleDriverProvider : CommonServiceImpl() {
busFragment = null
OchAutopilotAnalytics.ochEventKey = null
LineModel.release()
ScannerClientManager.release()
ScannerManager.release()
BusTrajectoryManager.release()
RepositoryManager.release()
}

View File

@@ -12,6 +12,7 @@ import com.mogo.eagle.core.utilcode.util.MultiDisplayUtils
import com.mogo.och.bridge.ui.autopilot.AutopilotState
import com.mogo.och.common.module.constant.OchCommonConst
import com.mogo.och.common.module.biz.provider.CommonServiceImpl
import com.mogo.och.common.module.biz.scanner.ScannerManager
import com.mogo.och.common.module.voice.OutOffVoice
import com.mogo.och.common.module.wigets.media.MediaPlayerActivity
import com.mogo.och.shuttle.weaknet.passenger.model.TicketModel

View File

@@ -4,13 +4,13 @@ import android.annotation.SuppressLint
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_BUS_P
import com.mogo.eagle.core.utilcode.util.GsonUtils
import com.mogo.och.common.module.biz.scanner.QrBean
import com.mogo.och.common.module.biz.scanner.ScannerManager
import com.mogo.och.common.module.manager.bluetooth.BleManager
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.och.common.module.manager.scnner.QrBean
import com.mogo.och.common.module.manager.socket.lan.LanSocketManager
import com.mogo.och.common.module.manager.scnner.ScannerManager
import com.mogo.och.common.module.manager.scnner.StateChangeListener
import com.mogo.och.common.module.biz.scanner.StateChangeListener
import com.mogo.och.common.module.manager.socket.lan.ILanMessageListener
import com.mogo.och.common.module.manager.socket.lan.bean.DPMsgType
import com.mogo.och.common.module.manager.socket.lan.bean.WriteOffDetialMsg
@@ -69,11 +69,14 @@ object TicketModel : StateChangeListener {
fun load(){
OchChainLogManager.writeChainLogInit("初始化信息","核销功能初始化")
ScannerManager.load()
ScannerManager.addStateChangeListener(TAG, this)
// 核销信息
LanSocketManager.registerSocketMessageListener(DPMsgType.TYPE_WRITEOFF_INFO_RESULT.type,writeOffResultMsg)
}
fun release(){
OchChainLogManager.writeChainLogInit("释放信息","核销功能释放")
ScannerManager.release()
ScannerManager.removeListener(TAG)
LanSocketManager.unRegisterSocketMessageListener(DPMsgType.TYPE_WRITEOFF_INFO_RESULT.type,writeOffResultMsg)
}

View File

@@ -43,7 +43,7 @@
android:layout_gravity="center"
android:layout_marginStart="@dimen/dp_40" />
<com.mogo.och.common.module.manager.scnner.ScannerStateView
<com.mogo.och.common.module.biz.scanner.ScannerStateView
android:id="@+id/scannerStateView"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"

View File

@@ -31,7 +31,7 @@
app:layout_constraintStart_toEndOf="@+id/wifiStateView"
app:layout_constraintTop_toTopOf="@+id/iv_logon" />
<com.mogo.och.common.module.manager.scnner.ScannerStateView
<com.mogo.och.common.module.biz.scanner.ScannerStateView
android:id="@+id/scannerStateView"
android:layout_width="@dimen/dp_24"
android:layout_height="@dimen/dp_24"