[6.8.0]
[fea] [核销、未通知小程序]
This commit is contained in:
@@ -1,6 +1,29 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.mogo.och.common.module">
|
||||
|
||||
<uses-permission android:name="android.permission.BLUETOOTH"
|
||||
android:maxSdkVersion="30" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
|
||||
android:maxSdkVersion="30" />
|
||||
|
||||
<uses-permission android:name="android.permission.BLUETOOTH"
|
||||
android:maxSdkVersion="30" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
|
||||
android:maxSdkVersion="30" />
|
||||
|
||||
<!--查找蓝牙设备-->
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||
|
||||
<!--使当前设备可被其他蓝牙设备检测到-->
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
||||
|
||||
<!--与已配对的蓝牙设备进行通讯-->
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
|
||||
<!--使用蓝牙扫描结果来推导物理位置-->
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
|
||||
<application>
|
||||
<activity
|
||||
android:name=".wigets.media.MediaPlayerActivity"
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.mogo.och.common.module.manager.bluetooth
|
||||
|
||||
import android.Manifest
|
||||
import android.bluetooth.BluetoothAdapter
|
||||
import android.bluetooth.BluetoothManager
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import androidx.core.app.ActivityCompat
|
||||
import com.mogo.commons.AbsMogoApplication
|
||||
import com.mogo.eagle.core.function.main.MainPresenter
|
||||
import com.mogo.eagle.core.utilcode.mogo.permissions.PermissionsDialogUtils
|
||||
import com.mogo.eagle.core.utilcode.util.ActivityUtils
|
||||
import com.mogo.eagle.core.utilcode.util.ToastUtils
|
||||
import com.mogo.och.common.module.utils.PermissionUtil
|
||||
|
||||
open class BaseBluetoothManager {
|
||||
|
||||
protected var bluetoothAdapter: BluetoothAdapter? = null
|
||||
protected var bluetoothManager: BluetoothManager? = null
|
||||
|
||||
private val REQUEST_ENABLE_BT = 10001
|
||||
private val TAG = "OchBluetoothManager"
|
||||
|
||||
private var permissionlist = arrayOf(
|
||||
Manifest.permission.BLUETOOTH_SCAN,
|
||||
Manifest.permission.BLUETOOTH_ADVERTISE,
|
||||
Manifest.permission.BLUETOOTH_CONNECT,
|
||||
Manifest.permission.ACCESS_FINE_LOCATION,
|
||||
Manifest.permission.ACCESS_COARSE_LOCATION,
|
||||
)
|
||||
|
||||
enum class BluetoothState {
|
||||
NONE, ON, OFF
|
||||
}
|
||||
|
||||
init {
|
||||
bluetoothManager = AbsMogoApplication.getApp().getSystemService(BluetoothManager::class.java)
|
||||
bluetoothAdapter = bluetoothManager?.adapter
|
||||
}
|
||||
|
||||
|
||||
fun isEnable(): BluetoothState {
|
||||
bluetoothAdapter?.let {
|
||||
if (it.isEnabled) {
|
||||
return BluetoothState.ON
|
||||
} else {
|
||||
return BluetoothState.OFF
|
||||
}
|
||||
}
|
||||
ToastUtils.showShort("设备无蓝牙硬件")
|
||||
return BluetoothState.NONE
|
||||
}
|
||||
fun requestPermission(){
|
||||
|
||||
if (PermissionUtil.checkPermission(AbsMogoApplication.getApp(), *permissionlist)) {
|
||||
|
||||
}else{
|
||||
//申请悬浮窗权限
|
||||
val shouldShowRequestPermissionRationale = ActivityUtils.getTopActivity()
|
||||
.shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)
|
||||
if(shouldShowRequestPermissionRationale){// 可以弹窗系统权限框
|
||||
ActivityCompat.requestPermissions(
|
||||
ActivityUtils.getTopActivity(),
|
||||
permissionlist, MainPresenter.MOGO_PERMISSION_REQUEST_CODE
|
||||
)
|
||||
}else{// 不会弹系统弹窗
|
||||
PermissionsDialogUtils.openAppDetails(ActivityUtils.getTopActivity(), "蓝牙", 100)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun checkPermission():Boolean{
|
||||
AbsMogoApplication.getApp()?.let {
|
||||
permissionlist.forEach { permission->
|
||||
val checkSelfPermission = ActivityCompat.checkSelfPermission(it, permission)
|
||||
if (PackageManager.PERMISSION_GRANTED!=checkSelfPermission) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.mogo.och.common.module.manager.bluetooth
|
||||
|
||||
import android.bluetooth.BluetoothDevice
|
||||
import android.bluetooth.le.ScanResult
|
||||
|
||||
data class BleDevItem(val dev: BluetoothDevice,val scanResult: ScanResult,val gattcallback:OchBluetoothGattCallback){
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as BleDevItem
|
||||
|
||||
return dev.address == other.dev.address
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return dev.hashCode()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package com.mogo.och.common.module.manager.bluetooth
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.bluetooth.le.BluetoothLeScanner
|
||||
import android.bluetooth.le.ScanCallback
|
||||
import android.bluetooth.le.ScanResult
|
||||
import android.os.Build
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import com.mogo.och.common.module.manager.loop.BizLoopManager
|
||||
import java.util.UUID
|
||||
|
||||
|
||||
object BleManager : BaseBluetoothManager() {
|
||||
|
||||
val UUID_SERVICE: UUID = UUID.fromString("000018F0-0000-1000-8000-00805F9BDDFB") //自定义UUID
|
||||
val UUID_CHAR_READ_NOTIFY: UUID = UUID.fromString("00002AF0-0000-1000-8000-00805F9BEEFB")
|
||||
val UUID_DESC_NOTITY: UUID = UUID.fromString("00002AF1-0000-1000-8000-00805F9BCCFB")
|
||||
val UUID_CHAR_WRITE: UUID = UUID.fromString("00002AF1-0000-1000-8000-00805F9BFFFB")
|
||||
|
||||
|
||||
private var scanning = false
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
|
||||
private var bluetoothLeScanner: BluetoothLeScanner? = null
|
||||
|
||||
private val SCAN_PERIOD = 10000L
|
||||
|
||||
private const val TAG = "BleManager"
|
||||
|
||||
private val scanList = mutableListOf<BleDevItem>()
|
||||
|
||||
var listener: BleDevListener? = null
|
||||
|
||||
private val leScanCallback = object : ScanCallback(){
|
||||
@SuppressLint("MissingPermission")
|
||||
override fun onScanResult(callbackType: Int, result: ScanResult?) {
|
||||
result?.let {
|
||||
val device = it.device
|
||||
it.rssi// 信号强度
|
||||
it.scanRecord?.advertiseFlags
|
||||
it.scanRecord?.serviceUuids
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
it.scanRecord?.serviceSolicitationUuids
|
||||
}
|
||||
it.scanRecord?.manufacturerSpecificData
|
||||
it.scanRecord?.serviceData
|
||||
it.scanRecord?.txPowerLevel
|
||||
it.scanRecord?.deviceName
|
||||
it.scanRecord?.manufacturerSpecificData
|
||||
|
||||
it.timestampNanos//
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
it.isLegacy
|
||||
} else {
|
||||
TODO("VERSION.SDK_INT < O")
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
it.isLegacy//是否传统蓝牙
|
||||
} else {
|
||||
TODO("VERSION.SDK_INT < O")
|
||||
}
|
||||
it.primaryPhy
|
||||
it.secondaryPhy
|
||||
it.advertisingSid
|
||||
it.txPower
|
||||
it.periodicAdvertisingInterval
|
||||
if(!it.device.name.isNullOrEmpty()){
|
||||
val bleDevItem = BleDevItem(result.device, result,OchBluetoothGattCallback(result.device))
|
||||
if(!scanList.contains(bleDevItem)){
|
||||
scanList.add(bleDevItem)
|
||||
}
|
||||
Log.d(TAG, "callbackType:${callbackType}_____result:${result}")
|
||||
listener?.dataChange(scanList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBatchScanResults(results: MutableList<ScanResult>?) {
|
||||
Log.d(TAG, "results:${results}")
|
||||
}
|
||||
|
||||
override fun onScanFailed(errorCode: Int) {
|
||||
Log.d(TAG, "errorCode:${errorCode}")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun scanLeDevice() {
|
||||
|
||||
when (isEnable()) {
|
||||
BluetoothState.ON -> {}
|
||||
else -> {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if(bluetoothLeScanner ==null){
|
||||
bluetoothLeScanner = bluetoothAdapter?.bluetoothLeScanner
|
||||
}
|
||||
|
||||
try {
|
||||
if (!scanning) { // Stops scanning after a pre-defined scan period.
|
||||
handler.postDelayed({
|
||||
scanning = false
|
||||
bluetoothLeScanner?.stopScan(leScanCallback)
|
||||
}, SCAN_PERIOD)
|
||||
scanning = true
|
||||
bluetoothLeScanner?.startScan(leScanCallback)
|
||||
scanList.clear()
|
||||
listener?.dataChange(scanList)
|
||||
} else {
|
||||
scanning = false
|
||||
bluetoothLeScanner?.stopScan(leScanCallback)
|
||||
}
|
||||
}catch (e:SecurityException){
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
interface BleDevListener{
|
||||
fun dataChange(scanList:MutableList<BleDevItem>)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
package com.mogo.och.common.module.manager.bluetooth
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.bluetooth.BluetoothDevice
|
||||
import android.bluetooth.BluetoothGatt
|
||||
import android.bluetooth.BluetoothGattCallback
|
||||
import android.bluetooth.BluetoothGattCharacteristic
|
||||
import android.bluetooth.BluetoothGattDescriptor
|
||||
import android.bluetooth.BluetoothGattService
|
||||
import android.bluetooth.BluetoothProfile
|
||||
import android.util.Log
|
||||
import com.mogo.commons.AbsMogoApplication
|
||||
import com.mogo.eagle.core.utilcode.util.ToastUtils
|
||||
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
|
||||
import java.util.UUID
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
class OchBluetoothGattCallback(device: BluetoothDevice) : BluetoothGattCallback() {
|
||||
|
||||
private val device = device
|
||||
private var mBluetoothGatt: BluetoothGatt? = null
|
||||
var connectListener: ConnectListener?=null
|
||||
|
||||
private val waitSendData = mutableMapOf<String,UUID>()
|
||||
|
||||
|
||||
var isConnected:Boolean by Delegates.observable(false) { _, oldValue, newValue ->
|
||||
if (oldValue != newValue) {
|
||||
Log.i(TAG,"链接状态发生变化")
|
||||
connectListener?.connectChangeListener()
|
||||
}
|
||||
}
|
||||
|
||||
private val TAG = "GattCallback"
|
||||
override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
|
||||
val dev = gatt.device
|
||||
Log.i(TAG, "onConnectionStateChange:${dev.name},${dev.address},${status},${newState},${dev.type}")
|
||||
if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_CONNECTED) {
|
||||
isConnected = true
|
||||
gatt.discoverServices() //启动服务发现
|
||||
} else {
|
||||
isConnected = false
|
||||
closeConn()
|
||||
}
|
||||
if(status==0){
|
||||
if(newState==2){
|
||||
Log.i(TAG,"与[${dev}]连接成功")
|
||||
}else{
|
||||
Log.i(TAG,"与[${dev}]连接断开")
|
||||
}
|
||||
}else{
|
||||
Log.i(TAG,"与[${dev}]连接出错,错误码:$status")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
|
||||
Log.i(TAG,"onServicesDiscovered:${gatt.device.name},${gatt.device.address},${status}")
|
||||
if (status == BluetoothGatt.GATT_SUCCESS) { //BLE服务发现成功
|
||||
// 遍历获取BLE服务Services/Characteristics/Descriptors的全部UUID
|
||||
for (service in gatt.services) {
|
||||
val allUUIDs = StringBuilder(
|
||||
"UUIDs={\n S=${service.uuid}".trimIndent()
|
||||
)
|
||||
for (characteristic in service.characteristics) {
|
||||
allUUIDs.append(",\nC=").append(characteristic.uuid)
|
||||
for (descriptor in characteristic.descriptors) {
|
||||
allUUIDs.append(",\nD=").append(descriptor.uuid)
|
||||
}
|
||||
}
|
||||
allUUIDs.append("}")
|
||||
Log.i(TAG, "onServicesDiscovered:$allUUIDs")
|
||||
}
|
||||
// 链接成功 服务发现也成功后
|
||||
waitSendData.forEach {
|
||||
writeData2UUID(it.key,it.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCharacteristicRead(
|
||||
gatt: BluetoothGatt,
|
||||
characteristic: BluetoothGattCharacteristic,
|
||||
status: Int
|
||||
) {
|
||||
val uuid = characteristic.uuid
|
||||
val valueStr = String(characteristic.value)
|
||||
Log.i(TAG,"onCharacteristicRead:${gatt.device.name},${gatt.device.address},$uuid,$valueStr,$status")
|
||||
}
|
||||
|
||||
override fun onCharacteristicWrite(
|
||||
gatt: BluetoothGatt,
|
||||
characteristic: BluetoothGattCharacteristic,
|
||||
status: Int
|
||||
) {
|
||||
val uuid = characteristic.uuid
|
||||
val valueStr = String(characteristic.value)
|
||||
Log.i(
|
||||
TAG,
|
||||
"onCharacteristicWrite:${gatt.device.name},${gatt.device.address},$uuid,$valueStr,$status"
|
||||
)
|
||||
if(status==BluetoothGatt.GATT_SUCCESS){
|
||||
waitSendData.remove(valueStr)
|
||||
closeConn()
|
||||
connectListener?.sendDataSuccessAndCloseListener(device)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCharacteristicChanged(
|
||||
gatt: BluetoothGatt,
|
||||
characteristic: BluetoothGattCharacteristic
|
||||
) {
|
||||
val uuid = characteristic.uuid
|
||||
val valueStr = String(characteristic.value)
|
||||
Log.i(TAG,"onCharacteristicChanged:${gatt.device.name},${ gatt.device.address},$uuid,$valueStr")
|
||||
}
|
||||
|
||||
override fun onDescriptorRead(
|
||||
gatt: BluetoothGatt,
|
||||
descriptor: BluetoothGattDescriptor,
|
||||
status: Int
|
||||
) {
|
||||
val uuid = descriptor.uuid
|
||||
val valueStr = descriptor.value.contentToString()
|
||||
Log.i(TAG,"onDescriptorRead:${gatt.device.name},${gatt.device.address},$uuid,$valueStr,$status")
|
||||
}
|
||||
|
||||
override fun onDescriptorWrite(
|
||||
gatt: BluetoothGatt,
|
||||
descriptor: BluetoothGattDescriptor,
|
||||
status: Int
|
||||
) {
|
||||
val uuid = descriptor.uuid
|
||||
val valueStr = descriptor.value.contentToString()
|
||||
Log.i(TAG,"onDescriptorWrite:${gatt.device.name},${gatt.device.address},$uuid,$valueStr,$status")
|
||||
}
|
||||
|
||||
private fun refreshDeviceCache(mBluetoothGatt: BluetoothGatt?): Boolean {
|
||||
if (mBluetoothGatt != null) {
|
||||
try {
|
||||
val refresh = mBluetoothGatt.javaClass.getMethod("refresh")
|
||||
if (refresh != null) {
|
||||
return refresh.invoke(mBluetoothGatt) as Boolean
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// BLE中心设备连接外围设备的数量有限(大概2~7个),在建立新连接之前必须释放旧连接资源,否则容易出现连接错误133
|
||||
fun closeConn() {
|
||||
if (mBluetoothGatt != null) {
|
||||
mBluetoothGatt!!.disconnect()
|
||||
mBluetoothGatt!!.close()
|
||||
refreshDeviceCache(mBluetoothGatt)
|
||||
mBluetoothGatt = null
|
||||
isConnected = false
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 获取Gatt服务
|
||||
private fun getGattService(uuid: UUID): BluetoothGattService? {
|
||||
if (!isConnected) {
|
||||
return null
|
||||
}
|
||||
val service = mBluetoothGatt!!.getService(uuid)
|
||||
if (service == null) ToastUtils.showShort("没有找到服务UUID=$uuid")
|
||||
return service
|
||||
}
|
||||
|
||||
// 注意:连续频繁读写数据容易失败,读写操作间隔最好200ms以上,或等待上次回调完成后再进行下次读写操作!
|
||||
// 写入数据成功会回调->onCharacteristicWrite()
|
||||
fun writeData2UUID(text:String,uuid: UUID){
|
||||
OchChainLogManager.writeChainLogWriteOff("司机端核销成功","发送数据${text}")
|
||||
val service = getGattService(BleManager.UUID_SERVICE)
|
||||
if (service != null) {
|
||||
val characteristic = service.getCharacteristic(uuid) //通过UUID获取可写的Characteristic
|
||||
characteristic.setValue(text.toByteArray()) //单次最多20个字节
|
||||
mBluetoothGatt!!.writeCharacteristic(characteristic)
|
||||
}
|
||||
}
|
||||
// 注意:连续频繁读写数据容易失败,读写操作间隔最好200ms以上,或等待上次回调完成后再进行下次读写操作!
|
||||
// 读取数据成功会回调->onCharacteristicChanged()
|
||||
fun readDataByUUId(uuid: UUID){
|
||||
val service = getGattService(BleManager.UUID_SERVICE)
|
||||
if (service != null) {
|
||||
val characteristic =
|
||||
service.getCharacteristic(uuid) //通过UUID获取可读的Characteristic
|
||||
mBluetoothGatt!!.readCharacteristic(characteristic)
|
||||
}
|
||||
}
|
||||
|
||||
fun notifyByUUID(uuid: UUID,notify:UUID){
|
||||
// 设置通知Characteristic变化会回调->onCharacteristicChanged()
|
||||
val service = getGattService(BleManager.UUID_SERVICE)
|
||||
if (service != null) {
|
||||
// 设置Characteristic通知
|
||||
val characteristic =
|
||||
service.getCharacteristic(BleManager.UUID_CHAR_READ_NOTIFY) //通过UUID获取可通知的Characteristic
|
||||
mBluetoothGatt!!.setCharacteristicNotification(characteristic, true)
|
||||
|
||||
// 向Characteristic的Descriptor属性写入通知开关,使蓝牙设备主动向手机发送数据
|
||||
val descriptor = characteristic.getDescriptor(BleManager.UUID_DESC_NOTITY)
|
||||
// descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);//和通知类似,但服务端不主动发数据,只指示客户端读取数据
|
||||
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE)
|
||||
mBluetoothGatt!!.writeDescriptor(descriptor)
|
||||
}
|
||||
}
|
||||
|
||||
fun connectGatt() {
|
||||
if(isConnected){
|
||||
ToastUtils.showShort("已连接成功")
|
||||
writeData2UUID("1",BleManager.UUID_CHAR_WRITE)
|
||||
}else {
|
||||
mBluetoothGatt = device.connectGatt(AbsMogoApplication.getApp(), false, this)
|
||||
waitSendData.put("1",BleManager.UUID_CHAR_WRITE)
|
||||
}
|
||||
}
|
||||
|
||||
interface ConnectListener{
|
||||
fun connectChangeListener(){}
|
||||
fun sendDataSuccessAndCloseListener(device: BluetoothDevice)
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,14 @@ object CheckVinManager : IMoGoAutopilotCarConfigListener {
|
||||
checkVin()
|
||||
}
|
||||
|
||||
fun getVin(): String {
|
||||
var delineVin = CallerAutoPilotControlManager.getVIN()
|
||||
if(delineVin.isEmpty()){
|
||||
delineVin = LoginStatusManager.getLoginInfo()?.vin?:""
|
||||
}
|
||||
return delineVin
|
||||
}
|
||||
|
||||
private fun checkVin() {
|
||||
LoginStatusManager.getLoginInfo()?.let {loginInfo ->
|
||||
val serverVin = loginInfo.vin
|
||||
|
||||
@@ -58,10 +58,16 @@ object OchChainLogManager {
|
||||
|
||||
const val EVENT_KEY_INFO_DB = "analytics_event_och_db"
|
||||
|
||||
const val EVENT_KEY_INFO_WRITEOFF = "analytics_event_och_writeoff"
|
||||
|
||||
|
||||
fun writeChainLogDb(title: String, info: String) {
|
||||
writeChainLog(title, info, true, EVENT_KEY_INFO_DB)
|
||||
}
|
||||
fun writeChainLogWriteOff(title: String, info: String) {
|
||||
writeChainLog(title, info, true, EVENT_KEY_INFO_WRITEOFF)
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun writeChainLogNet(mustUpdate: Boolean, title: String, info: String) {
|
||||
|
||||
@@ -77,7 +77,7 @@ data class WriteOffDetialMsg(
|
||||
val bookingTime: Long?=null,
|
||||
val businessType: Int?=null,
|
||||
val lineId: Long?=null,
|
||||
val remainingTimes: Int?=null,//剩余票数
|
||||
val availableTimes: Int?=null,//剩余票数
|
||||
val orderNo: String?=null,
|
||||
val uid: String?=null,
|
||||
val phone: String?=null,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 5,
|
||||
"identityHash": "17bc11cdabb03126bdab91081b897fff",
|
||||
"identityHash": "018ed967c5f335de5d39581e033160ed",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "contrail_data_table",
|
||||
@@ -593,7 +593,7 @@
|
||||
},
|
||||
{
|
||||
"tableName": "writeoff_data_table",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `msg_id` TEXT, `expiry_time` INTEGER, `booking_time` INTEGER, `type` INTEGER, `task_id` INTEGER, `line_id` INTEGER, `site_id` INTEGER, `driver_id` INTEGER, `remaining_times` INTEGER, `order_no` TEXT, `uid` TEXT, `seq` TEXT, `business_time` INTEGER, `tick_size` INTEGER, `tick_name` TEXT, `event_save_time` INTEGER NOT NULL, `update_status` INTEGER NOT NULL, `update_time` INTEGER)",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `msg_id` TEXT, `expiry_time` INTEGER, `booking_time` INTEGER, `type` INTEGER, `task_id` INTEGER, `line_id` INTEGER, `site_id` INTEGER, `driver_id` INTEGER, `available_times` INTEGER, `order_no` TEXT, `uid` TEXT, `seq` TEXT, `business_time` INTEGER, `tick_size` INTEGER, `tick_name` TEXT, `event_save_time` INTEGER NOT NULL, `update_status` INTEGER NOT NULL, `update_time` INTEGER)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
@@ -650,8 +650,8 @@
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "remainingTimes",
|
||||
"columnName": "remaining_times",
|
||||
"fieldPath": "availableTimes",
|
||||
"columnName": "available_times",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
@@ -733,7 +733,7 @@
|
||||
"views": [],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '17bc11cdabb03126bdab91081b897fff')"
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '018ed967c5f335de5d39581e033160ed')"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -3,13 +3,14 @@ package com.mogo.och.weaknet.bean.request
|
||||
import com.mogo.commons.storage.SharedPrefsMgr
|
||||
import com.mogo.eagle.core.network.utils.digest.DigestUtils
|
||||
import com.mogo.och.common.module.biz.login.LoginStatusManager
|
||||
import com.mogo.och.common.module.manager.device.checkvin.CheckVinManager
|
||||
import com.mogo.och.weaknet.repository.db.bean.EventDataBean
|
||||
import com.mogo.och.weaknet.repository.db.bean.WriteOffDataBean
|
||||
|
||||
/**
|
||||
* 上报事件
|
||||
*/
|
||||
data class ShuttleEventRequest(val requestId: String, val sn: String, val businessType: Int,val eventList:MutableList<Event>){
|
||||
data class ShuttleEventRequest(val requestId: String, val sn: String,val vin:String ,val businessType: Int,val eventList:MutableList<Event>){
|
||||
companion object{
|
||||
fun transformDb2Net(
|
||||
waitUpdateEvent: List<EventDataBean>?,
|
||||
@@ -32,7 +33,7 @@ data class ShuttleEventRequest(val requestId: String, val sn: String, val busine
|
||||
eventList4Request.add(tempEvent!!)
|
||||
}
|
||||
val md5Hex = DigestUtils.md5Hex(eventList4Request.toString())
|
||||
return ShuttleEventRequest(md5Hex, SharedPrefsMgr.getInstance().sn,
|
||||
return ShuttleEventRequest(md5Hex, SharedPrefsMgr.getInstance().sn, CheckVinManager.getVin(),
|
||||
businessTypeShuttle,eventList4Request)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,8 +63,8 @@ data class WriteOffDataBean(
|
||||
/**
|
||||
* 剩余核销次数>0
|
||||
*/
|
||||
@ColumnInfo(name = "remaining_times", typeAffinity = ColumnInfo.INTEGER)
|
||||
var remainingTimes: Int? = null,
|
||||
@ColumnInfo(name = "available_times", typeAffinity = ColumnInfo.INTEGER)
|
||||
var availableTimes: Int? = null,
|
||||
|
||||
/**
|
||||
* 订单号
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.mogo.eagle.core.utilcode.mogo.AppIdentityModeUtils
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
|
||||
import com.mogo.och.common.module.biz.login.LoginStatusManager
|
||||
import com.mogo.och.common.module.manager.autopilot.line.LineManager
|
||||
import com.mogo.och.common.module.manager.cache.OchSPManager
|
||||
import com.mogo.och.common.module.manager.socket.lan.bean.WriteOffDetialMsg
|
||||
import com.mogo.och.common.module.network.OchCommonServiceCallback
|
||||
import com.mogo.och.common.module.utils.DateTimeUtil
|
||||
@@ -126,7 +127,7 @@ class WriteOffCacheRepository : IWriteOffRepository {
|
||||
|
||||
if(AppIdentityModeUtils.isShuttle(FunctionBuildConfig.appIdentityMode)) {
|
||||
// 6、校验次数
|
||||
if((it.remainingTimes?:0)<=0){
|
||||
if((it.availableTimes?:0)<=0){
|
||||
throw DataException(1008,"车票剩余可用次数为0")
|
||||
}
|
||||
// 7、同一个订单2分钟内只能核销一次
|
||||
@@ -140,6 +141,8 @@ class WriteOffCacheRepository : IWriteOffRepository {
|
||||
}else{
|
||||
throw DataException(11000,"缺少orderNo")
|
||||
}
|
||||
val (start, _) = LineManager.getStations()
|
||||
siteId = start?.siteId?.toLong()?:0
|
||||
}else if(AppIdentityModeUtils.isBus(FunctionBuildConfig.appIdentityMode)) {
|
||||
val (start, _) = LineManager.getStations()
|
||||
if(start?.siteId?.toLong()==it.startStationId){
|
||||
@@ -156,15 +159,17 @@ class WriteOffCacheRepository : IWriteOffRepository {
|
||||
addWrite.taskId = LineModel.currentTask?.taskId
|
||||
addWrite.lineId = lineId
|
||||
addWrite.siteId = siteId
|
||||
addWrite.remainingTimes = it.remainingTimes
|
||||
addWrite.availableTimes = it.availableTimes
|
||||
addWrite.orderNo = it.orderNo
|
||||
addWrite.uid = it.uid
|
||||
addWrite.phone = it.phone
|
||||
addWrite.ticketSize = it.ticketSize
|
||||
addWrite.ticketName = it.ticketName
|
||||
WriteOffDb.addOrUpdate()
|
||||
|
||||
val reslut = PassengerWriteOffResponse.Result(it.phone,it.ticketSize,it.ticketName,it.remainingTimes?.toLong())
|
||||
addWrite.msgId = OchSPManager.getSn()+System.currentTimeMillis()
|
||||
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())
|
||||
return@flatMap Observable.just(reslut)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,4 +2,6 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.mogo.och.shuttle.weaknet.passenger">
|
||||
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
</manifest>
|
||||
@@ -1,9 +1,17 @@
|
||||
package com.mogo.och.shuttle.weaknet.passenger.model
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.bluetooth.BluetoothDevice
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
|
||||
import com.mogo.eagle.core.utilcode.mogo.logger.scene.SceneConstant.Companion.M_BUS_P
|
||||
import com.mogo.eagle.core.utilcode.util.GsonUtils
|
||||
import com.mogo.eagle.core.utilcode.util.RegexUtils
|
||||
import com.mogo.och.common.module.manager.bluetooth.BleDevItem
|
||||
import com.mogo.och.common.module.manager.bluetooth.BleManager
|
||||
import com.mogo.och.common.module.manager.bluetooth.BleManager.BleDevListener
|
||||
import com.mogo.och.common.module.manager.bluetooth.OchBluetoothGattCallback.ConnectListener
|
||||
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.socket.lan.LanSocketManager
|
||||
import com.mogo.och.common.module.manager.scnner.ScannerManager
|
||||
import com.mogo.och.common.module.manager.scnner.StateChangeListener
|
||||
@@ -11,31 +19,92 @@ 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
|
||||
import com.mogo.och.common.module.manager.socket.lan.bean.WriteOffResultMsg
|
||||
import com.mogo.och.common.module.utils.RxUtils
|
||||
import java.net.URLDecoder
|
||||
|
||||
object TicketModel : StateChangeListener {
|
||||
|
||||
private const val TAG = "TicketModel"
|
||||
|
||||
// 等待链接
|
||||
private val waitConnectDev = mutableListOf<BleDevItem>()
|
||||
private val waitConnectDevNameList = mutableListOf<String>()
|
||||
|
||||
private val connectListener: ConnectListener = object : ConnectListener {
|
||||
override fun sendDataSuccessAndCloseListener(device: BluetoothDevice) {
|
||||
waitConnectDev.forEach {
|
||||
if(it.dev==device){
|
||||
waitConnectDev.remove(it)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
|
||||
}
|
||||
|
||||
private val writeOffResultMsg = object : ILanMessageListener<WriteOffResultMsg> {
|
||||
override fun targetLan(): Class<WriteOffResultMsg> = WriteOffResultMsg::class.java
|
||||
|
||||
override fun onLanMsgReceived(obj: WriteOffResultMsg?) {
|
||||
// 收到核销结果扫描蓝牙并写会核销结果
|
||||
findDeviceConnectAndSendData(obj,1)
|
||||
}
|
||||
}
|
||||
@SuppressLint("MissingPermission")
|
||||
private fun findDeviceConnectAndSendData(obj: WriteOffResultMsg?,count:Int){
|
||||
OchChainLogManager.writeChainLogWriteOff("司机端核销成功","去连接蓝牙并发送数据 次数:${count}")
|
||||
// 收到核销结果扫描蓝牙并写会核销结果
|
||||
obj?.phone?.let {phone->
|
||||
var haveDevices = false
|
||||
waitConnectDev.forEach {
|
||||
if(it.dev.name== getBleName(phone)){
|
||||
haveDevices = true
|
||||
OchChainLogManager.writeChainLogWriteOff("司机端核销成功","找到设备")
|
||||
it.gattcallback.connectGatt()
|
||||
it.gattcallback.connectListener = connectListener
|
||||
}
|
||||
}
|
||||
if(!haveDevices&&count<6){
|
||||
RxUtils.createSubscribe {
|
||||
OchChainLogManager.writeChainLogWriteOff("司机端核销成功","2s后重试")
|
||||
findDeviceConnectAndSendData(obj,count+1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val bleDevs = object : BleDevListener{
|
||||
@SuppressLint("MissingPermission")
|
||||
@Synchronized
|
||||
override fun dataChange(scanList: MutableList<BleDevItem>) {
|
||||
val tempList = mutableListOf<String>()
|
||||
waitConnectDevNameList.forEach { waitConnectName->
|
||||
scanList.forEach {
|
||||
if(it.dev.name==waitConnectName){
|
||||
waitConnectDev.add(it)
|
||||
tempList.add(waitConnectName)
|
||||
}
|
||||
}
|
||||
}
|
||||
waitConnectDevNameList.removeAll(tempList)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun load(){
|
||||
OchChainLogManager.writeChainLogInit("初始化信息","核销功能初始化")
|
||||
ScannerManager.addStateChangeListener(TAG, this)
|
||||
// 核销信息
|
||||
LanSocketManager.registerSocketMessageListener(DPMsgType.TYPE_WRITEOFF_INFO_RESULT.type,writeOffResultMsg)
|
||||
|
||||
BleManager.listener = bleDevs
|
||||
}
|
||||
fun release(){
|
||||
ScannerManager.removeListener(TAG)
|
||||
LanSocketManager.unRegisterSocketMessageListener(DPMsgType.TYPE_WRITEOFF_INFO_RESULT.type,writeOffResultMsg)
|
||||
BleManager.listener = null
|
||||
}
|
||||
|
||||
override fun parseData(params: MutableMap<String, String>, payload: String?) {
|
||||
@@ -43,7 +112,7 @@ object TicketModel : StateChangeListener {
|
||||
val bookingTime = params["bookingTime"]
|
||||
val businessType = params["businessType"]
|
||||
val lineId = params["lineId"]
|
||||
val remainingTimes = params["remainingTimes"]
|
||||
val availableTimes = params["availableTimes"]
|
||||
val orderNo = params["orderNo"]
|
||||
val uid = params["uid"]
|
||||
val phone = params["phone"]
|
||||
@@ -67,12 +136,12 @@ object TicketModel : StateChangeListener {
|
||||
bookingTime?.toLong()?:0,
|
||||
businessType?.toInt()?:0,
|
||||
lineId?.toLong()?:0,
|
||||
remainingTimes?.toInt()?:0,
|
||||
availableTimes?.toInt()?:0,
|
||||
orderNo,
|
||||
uid,
|
||||
phoneNum,
|
||||
ticketSize?.toInt()?:0,
|
||||
ticketName,
|
||||
URLDecoder.decode(ticketName,"UTF-8"),
|
||||
type,
|
||||
pipe,
|
||||
startStationId?.toLong()?:0,
|
||||
@@ -80,6 +149,8 @@ object TicketModel : StateChangeListener {
|
||||
)
|
||||
CallerLogger.d(M_BUS_P + TAG, "sendTaskDetailsToClients = " + GsonUtils.toJson(writeOffDetail))
|
||||
LanSocketManager.sendMsgToServer(writeOffDetail)
|
||||
addWaitConnectDevName(phone)
|
||||
scanBle()
|
||||
}catch (e:Exception){
|
||||
e.printStackTrace()
|
||||
CallerLogger.d(M_BUS_P + TAG, "")
|
||||
@@ -95,4 +166,32 @@ object TicketModel : StateChangeListener {
|
||||
LanSocketManager.sendMsgToServer(writeOffDetail)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addWaitConnectDevName(phone: String?) {
|
||||
var tempPhone = phone
|
||||
tempPhone?.let {
|
||||
waitConnectDevNameList.add( getBleName(it))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun getBleName(phone: String):String{
|
||||
var tempPhone = phone
|
||||
tempPhone.let {
|
||||
if (it.length > 8) {
|
||||
//截取电话号码前三位
|
||||
val phoneNumPre = it.substring(0, 3)
|
||||
//截取电话号码后四位
|
||||
val phoneNumFix = it.substring(7)
|
||||
tempPhone = "mogo${phoneNumPre}$phoneNumFix"
|
||||
}
|
||||
}
|
||||
return tempPhone
|
||||
}
|
||||
|
||||
private fun scanBle() {
|
||||
BizLoopManager.runInMainThread{
|
||||
BleManager.scanLeDevice()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -401,7 +401,7 @@ open class MainActivity : MvpActivity<MainView?, MainPresenter?>(), MainView,
|
||||
// 弹出对话框告诉用户需要权限的原因, 并引导用户去应用权限管理中手动打开权限按钮
|
||||
if (!isFirst) {
|
||||
if (reasong.isNotEmpty()) {
|
||||
val substring = reasong.substring(0, reasong.length - 2)
|
||||
val substring = reasong.substring(0, reasong.length - 1)
|
||||
PermissionsDialogUtils.openAppDetails(this, substring, REQUEST_CODE_DIALOG)
|
||||
}else {
|
||||
PermissionsDialogUtils.openAppDetails(this, null, REQUEST_CODE_DIALOG)
|
||||
|
||||
Reference in New Issue
Block a user