[fix]
[蓝牙更多的监听]
This commit is contained in:
yangyakun
2024-11-25 20:39:58 +08:00
parent 72a713eb55
commit fa053b81c7
4 changed files with 160 additions and 17 deletions

View File

@@ -3,7 +3,10 @@ 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.ScanFilter
import android.bluetooth.le.ScanResult
import android.bluetooth.le.ScanSettings
import android.os.ParcelUuid
import android.util.Log
import com.mogo.och.common.module.utils.RxUtils
import java.util.UUID
@@ -11,7 +14,8 @@ import java.util.UUID
object BleManager : BaseBluetoothManager() {
val UUID_SERVICE: UUID = UUID.fromString("000018F0-0000-1000-8000-00805F9BDDFB") //自定义UUID
val UUID_SERVICE_String:String = "000018F0-0000-1000-8000-00805F9BDDFB"
val UUID_SERVICE: UUID = UUID.fromString(UUID_SERVICE_String) //自定义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")
@@ -24,6 +28,7 @@ object BleManager : BaseBluetoothManager() {
private val SCAN_PERIOD = 60_000L
private const val TAG = "BleManager"
private const val TAG1 = "GattCallback"
// 未连接到的设备
val scanList = mutableListOf<OchBluetoothGattCallback>()
@@ -41,6 +46,7 @@ object BleManager : BaseBluetoothManager() {
val bleDevItem = OchBluetoothGattCallback(result.device)
if(!scanList.contains(bleDevItem)){
scanList.add(bleDevItem)
Log.d(TAG1, "添加item scanList个数:${scanList.size}")
}
Log.d(TAG, "callbackType:${callbackType}_____result:${result}")
}
@@ -49,6 +55,7 @@ object BleManager : BaseBluetoothManager() {
}
@SuppressLint("MissingPermission")
fun scanLeDevice() {
when (isEnable()) {
@@ -69,7 +76,13 @@ object BleManager : BaseBluetoothManager() {
bluetoothLeScanner?.stopScan(leScanCallback)
}
scanning = true
bluetoothLeScanner?.startScan(leScanCallback)
val filters = mutableListOf<ScanFilter>()
val filter = ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString(UUID_SERVICE_String)).build()
filters.add(filter);
val scanSettings = ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build()
bluetoothLeScanner?.startScan(filters,scanSettings,leScanCallback)
scanList.clear()
}
}catch (e:SecurityException){
@@ -81,6 +94,13 @@ object BleManager : BaseBluetoothManager() {
@SuppressLint("MissingPermission")
fun sendData2Wx(devName: String, data: String): Boolean {
var needDev:OchBluetoothGattCallback?=null
sendDataIntDev.forEach {
if(it.device.name==devName){
it.connectGattAndSend(data)
return true
}
}
scanList.forEach {
if(it.device.name==devName){
needDev = it
@@ -90,7 +110,10 @@ object BleManager : BaseBluetoothManager() {
needDev?.let {
it.connectGattAndSend(data)
scanList.remove(it)
sendDataIntDev.add(it)
if(!sendDataIntDev.contains(it)) {
sendDataIntDev.add(it)
}
Log.d(TAG, "发送数据 scanList个数:${scanList.size}___sendDataIntDev个数:${sendDataIntDev.size}")
if (sendDataIntDev.size > maxConnectCount) {
sendDataIntDev.first().tryCloseConn()
}
@@ -101,7 +124,16 @@ object BleManager : BaseBluetoothManager() {
fun copy2ScanList(ochBluetoothGattCallback: OchBluetoothGattCallback) {
sendDataIntDev.remove(ochBluetoothGattCallback)
scanList.add(ochBluetoothGattCallback)
if(!scanList.contains(ochBluetoothGattCallback)){
scanList.add(ochBluetoothGattCallback)
}
Log.d(TAG1, "超时返回 scanList个数:${scanList.size}___sendDataIntDev个数:${sendDataIntDev.size}")
}
fun removeFromScandAndWrite(ochBluetoothGattCallback: OchBluetoothGattCallback) {
sendDataIntDev.remove(ochBluetoothGattCallback)
scanList.remove(ochBluetoothGattCallback)
Log.d(TAG1, "链接超次 scanList个数:${scanList.size}___sendDataIntDev个数:${sendDataIntDev.size}")
}
}

View File

@@ -2,6 +2,7 @@ package com.mogo.och.common.module.manager.bluetooth
import android.annotation.SuppressLint
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothDevice.TRANSPORT_LE
import android.bluetooth.BluetoothGatt
import android.bluetooth.BluetoothGattCallback
import android.bluetooth.BluetoothGattCharacteristic
@@ -20,6 +21,10 @@ import kotlin.properties.Delegates
@SuppressLint("MissingPermission")
class OchBluetoothGattCallback(device: BluetoothDevice) : BluetoothGattCallback() {
// 连接超时
// 写超时
private val _device = device
val device:BluetoothDevice
get() {
@@ -36,16 +41,36 @@ class OchBluetoothGattCallback(device: BluetoothDevice) : BluetoothGattCallback(
private var timeoutCLose: Disposable? = null
private var writeOut: Disposable? = null
private var isDestory = false
var isConnected:Boolean by Delegates.observable(false) { _, oldValue, newValue ->
if (oldValue != newValue) {
Log.i(TAG,"${device.name}:链接状态发生变化${newValue}")
if(!newValue){
OchChainLogManager.writeChainLogBluetooth("连接","连接断开")
closeAndDestory()
}
}
}
private val TAG = "GattCallback"
fun closeAndDestory(){
isDestory = true
closeConn(false)
BleManager.removeFromScandAndWrite(this)
}
/**
* @param
* @param gatt [android.bluetooth.BluetoothProfile.STATE_CONNECTED] 连接成功
* [android.bluetooth.BluetoothProfile.STATE_CONNECTING] 蓝牙连接中
* [android.bluetooth.BluetoothProfile.STATE_DISCONNECTED] 连接失败
* [android.bluetooth.BluetoothProfile.STATE_DISCONNECTING] 连接失败
* @param status
* @param newState
*/
override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
val dev = gatt.device
@@ -57,12 +82,21 @@ class OchBluetoothGattCallback(device: BluetoothDevice) : BluetoothGattCallback(
gatt.discoverServices() //启动服务发现
}else{
isConnected = false
closeConn(false)
connect()
Log.i(TAG,"与[${dev.name}]连接断开")
}
}else{
Log.i(TAG,"与[${dev.name}]连接出错,错误码:$status")
connect()
when (status) {
8 -> {
closeAndDestory()
}
else -> {
connect()
}
}
}
}
@@ -71,9 +105,7 @@ class OchBluetoothGattCallback(device: BluetoothDevice) : BluetoothGattCallback(
if (status == BluetoothGatt.GATT_SUCCESS) { //BLE服务发现成功
// 遍历获取BLE服务Services/Characteristics/Descriptors的全部UUID
// 链接成功 服务发现也成功后
waitSendData.forEach {
writeData2UUID(it.key,it.value)
}
sendData()
}
}
@@ -99,14 +131,16 @@ class OchBluetoothGattCallback(device: BluetoothDevice) : BluetoothGattCallback(
"onCharacteristicWrite:${gatt.device.name},${gatt.device.address},$uuid,$valueStr,$status"
)
if(status==BluetoothGatt.GATT_SUCCESS){
OchChainLogManager.writeChainLogWriteOff("司机端核销成功","${device.name}:发送数据${valueStr} 小程序接受成功")
OchChainLogManager.writeChainLogBluetooth("写入","${device.name}:发送数据${valueStr} 小程序接受成功")
waitSendData.remove(valueStr)
if(waitSendData.isEmpty()){
RxUtils.disposeSubscribe(timeoutCLose)
timeoutCLose = RxUtils.createSubscribeOnOwnThread(10_000) {
closeConn()
closeConn(true)
}
}
}else{
OchChainLogManager.writeChainLogBluetooth("写入","${device.name}:发送数据${valueStr} 写入失败")
}
}
@@ -125,20 +159,22 @@ class OchBluetoothGattCallback(device: BluetoothDevice) : BluetoothGattCallback(
if (waitSendData.isNotEmpty()) {
return
}else{
closeConn()
closeConn(true)
}
}
}
// BLE中心设备连接外围设备的数量有限(大概2~7个)在建立新连接之前必须释放旧连接资源否则容易出现连接错误133
fun closeConn() {
fun closeConn(needCopy:Boolean) {
if (mBluetoothGatt != null) {
mBluetoothGatt?.disconnect()
mBluetoothGatt?.close()
mBluetoothGatt = null
currentTryCount = 0
isConnected = false
BleManager.copy2ScanList(this)
if(needCopy&&!isDestory) {
BleManager.copy2ScanList(this)
}
}
}
@@ -161,6 +197,20 @@ class OchBluetoothGattCallback(device: BluetoothDevice) : BluetoothGattCallback(
val characteristic = service.getCharacteristic(uuid) //通过UUID获取可写的Characteristic
characteristic.setValue(text.toByteArray()) //单次最多20个字节
mBluetoothGatt!!.writeCharacteristic(characteristic)
// 设置写超时
RxUtils.disposeSubscribe(timeoutCLose)
timeoutCLose = RxUtils.createSubscribeOnOwnThread(15_000) {
// 删除正在发送的
waitSendData.remove(text)
if(waitSendData.isEmpty()){
OchChainLogManager.writeChainLogBluetooth("写数据","写15s超时")
closeAndDestory()
}
sendData()
}
}else{
OchChainLogManager.writeChainLogBluetooth("发现服务","server 为null 没有链接服务")
closeAndDestory()
}
}
@@ -169,20 +219,63 @@ class OchBluetoothGattCallback(device: BluetoothDevice) : BluetoothGattCallback(
if(isConnected){
ToastUtils.showShort("已连接成功")
OchChainLogManager.writeChainLogWriteOff("司机端核销成功","已连接成功")
writeData2UUID(data,BleManager.UUID_CHAR_WRITE)
waitSendData[data] = BleManager.UUID_CHAR_WRITE
sendData()
}else {
if (isDestory) {
OchChainLogManager.writeChainLogBluetooth("连接","已销毁")
closeAndDestory()
return
}
connect()
waitSendData[data] = BleManager.UUID_CHAR_WRITE
}
}
/**
* 链接成功后发送
* 写超时后 写下一条
*/
private fun sendData() {
waitSendData.firstNotNullOf {
if(RxUtils.isNotDisposed(writeOut)){
return
}
writeData2UUID(it.key,it.value)
}
}
/**
* 连接失败
* 连接失败
* 发送数据
*/
private fun connect(){
Log.i(TAG,"connect:第${currentTryCount}")
// 重试5次
if(currentTryCount>maxTryCount){
if(currentTryCount>maxTryCount||isDestory){
// 重新扫描该设备
OchChainLogManager.writeChainLogBluetooth("连接","超过次数")
closeAndDestory()
return
}
currentTryCount += 1
mBluetoothGatt = _device.connectGatt(AbsMogoApplication.getApp(), false, this)
val temp = currentTryCount
closeConn(false)
currentTryCount = temp
mBluetoothGatt = _device.connectGatt(AbsMogoApplication.getApp(), false, this, TRANSPORT_LE)
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as OchBluetoothGattCallback
return _device.name == other._device.name && _device.address== other._device.address
}
override fun hashCode(): Int {
return _device.hashCode()
}
}

View File

@@ -60,10 +60,15 @@ object OchChainLogManager {
const val EVENT_KEY_INFO_WRITEOFF = "analytics_event_och_writeoff"
const val EVENT_KEY_INFO_BLUETOOTH = "analytics_event_och_bluetooth"
fun writeChainLogDb(title: String, info: String) {
writeChainLog(title, info, true, EVENT_KEY_INFO_DB)
}
fun writeChainLogBluetooth(title: String, info: String) {
writeChainLog(title, info, true, EVENT_KEY_INFO_BLUETOOTH)
}
fun writeChainLogWriteOff(title: String, info: String) {
writeChainLog(title, info, true, EVENT_KEY_INFO_WRITEOFF)
}

View File

@@ -18,8 +18,11 @@ import com.mogo.eagle.core.function.call.setting.CallerSkinModeListenerManager
import com.mogo.eagle.core.utilcode.kotlin.*
import com.mogo.eagle.core.utilcode.util.ClickUtils
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.och.common.module.manager.bluetooth.BleManager
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.och.shuttle.weaknet.passenger.R
import kotlinx.android.synthetic.main.shuttle_p_m2_view_status_bar.view.aciv_wait_ele
import kotlinx.android.synthetic.main.shuttle_p_m2_view_status_bar.view.iv_logon
import kotlinx.android.synthetic.main.shuttle_p_m2_view_status_bar.view.progress
import kotlinx.android.synthetic.main.shuttle_p_m2_view_status_bar.view.tv_power_cos
import kotlinx.coroutines.*
@@ -71,6 +74,16 @@ class M2StatusBarView @JvmOverloads constructor(
tv_power_cos?.also {
it.text = "检测中"
}
iv_logon.onClick {
BizLoopManager.runInMainThread{
BleManager.scanLeDevice()
}
}
tv_power_cos.onClick {
BizLoopManager.runInIoThread {
BleManager.sendData2Wx("1889480", "00,${System.currentTimeMillis()}")
}
}
}
override fun onSkinModeChange(skinMode: Int) {