diff --git a/app/build.gradle b/app/build.gradle index 3d7eed3..c2051fb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -30,7 +30,7 @@ android { targetSdkVersion 35 versionCode 2112 // versionName "2.1.12" - versionName "2.1.12-Beta1" + versionName "2.1.12-Beta2" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/app/src/main/java/com/abbidot/tracker/ui/activity/HomeV2Activity.kt b/app/src/main/java/com/abbidot/tracker/ui/activity/HomeV2Activity.kt index 024fdf3..4d33214 100644 --- a/app/src/main/java/com/abbidot/tracker/ui/activity/HomeV2Activity.kt +++ b/app/src/main/java/com/abbidot/tracker/ui/activity/HomeV2Activity.kt @@ -49,7 +49,6 @@ import com.abbidot.tracker.ui.fragment.data.ActivityV2Fragment import com.abbidot.tracker.ui.fragment.data.RouteV2Fragment import com.abbidot.tracker.ui.fragment.map.MapV3Fragment import com.abbidot.tracker.ui.fragment.pet.PetV2Fragment -import com.abbidot.tracker.util.BleReportManage import com.abbidot.tracker.util.SocketUtilManage import com.abbidot.tracker.util.Util import com.abbidot.tracker.util.ViewUtil @@ -120,12 +119,12 @@ class HomeV2Activity : BaseActivity(ActivityHomeV2Binding private var mBleListenerReceiver: BluetoothMonitorReceiver? = null private var mSocketUtilManage: SocketUtilManage? = null - private val mBleReportManage: BleReportManage by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { - mSocketUtilManage = SocketUtilManage() - mSocketUtilManage?.initEasySocket(mContext) - LogUtil.e("创建Socket连接") - BleReportManage(mSocketSendMessageViewModel, mSocketUtilManage!!) - } +// private val mBleReportManage: BleReportManage by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { +// mSocketUtilManage = SocketUtilManage() +// mSocketUtilManage?.initEasySocket(mContext) +// LogUtil.e("创建Socket连接") +// BleReportManage(mSocketSendMessageViewModel, mSocketUtilManage!!) +// } override fun getTopBar(): QMUITopBar? = null @@ -344,9 +343,9 @@ class HomeV2Activity : BaseActivity(ActivityHomeV2Binding XEventBus.observe(this, EventName.BleReport) { receiveData: ReceiveDeviceData -> lifecycleScope.launch(Dispatchers.IO) { getPet(false)?.apply { - if (macID == receiveData.mac) { - mBleReportManage.dealBleReportData(receiveData.mac, receiveData.data) - } +// if (macID == receiveData.mac) { +// mBleReportManage.dealBleReportData(receiveData.mac, receiveData.data) +// } } } } diff --git a/app/src/main/java/com/abbidot/tracker/util/SocketUtilManageV2.kt b/app/src/main/java/com/abbidot/tracker/util/SocketUtilManageV2.kt new file mode 100644 index 0000000..cef04f0 --- /dev/null +++ b/app/src/main/java/com/abbidot/tracker/util/SocketUtilManageV2.kt @@ -0,0 +1,114 @@ +package com.abbidot.tracker.util + +import android.content.Context +import com.abbidot.baselibrary.util.AppUtils +import com.abbidot.baselibrary.util.LogUtil +import com.abbidot.tracker.util.bluetooth.SRBleCmdUtil +import com.abbidot.tracker.util.bluetooth.SRBleUtil +import com.clj.fastble.utils.HexUtil +import com.easysocket.EasySocket +import com.easysocket.config.EasySocketOptions +import com.easysocket.entity.OriginReadData +import com.easysocket.entity.SocketAddress +import com.easysocket.interfaces.conn.ISocketActionListener + + +/** + *Created by .yzq on 2025/4/18/018. + * @link + * @description: + */ +class SocketUtilManageV2 { + + private var mNeedSendMessage = byteArrayOf() + private var mMac = "" + + @Synchronized + fun initEasySocket(context: Context, mac: String, data: ByteArray) { + val data1 = SRBleCmdUtil.instance.byteToInt(data[1]) + val data2 = SRBleCmdUtil.instance.byteToInt(data[2]) + val data3 = SRBleCmdUtil.instance.byteToInt(data[3]) + val data4 = SRBleCmdUtil.instance.byteToInt(data[4]) + val ip = "$data1.$data2.$data3.$data4" + val port = SRBleCmdUtil.instance.byte2ArrayToInt(data.sliceArray(5..6)) + LogUtil.e("$ip:$port") + mMac = mac + mNeedSendMessage = data.sliceArray(8..data.size - 2) + initEasySocket(context, ip, port) + } + + /** + * 初始化EasySocket + */ + private fun initEasySocket(context: Context, ip: String, port: Int) { + //socket配置 + val options = EasySocketOptions.Builder().setSocketAddress(SocketAddress(ip, port)) + .setMaxWriteBytes(300) + // 强烈建议定义一个消息协议,方便解决 socket黏包、分包的问题 + // .setReaderProtocol(new DefaultMessageProtocol()) // 默认的消息协议 + .build() + //初始化EasySocket + EasySocket.getInstance().createConnection(options, context).setDebug(AppUtils.isDebug()) + + //监听socket相关行为 + EasySocket.getInstance().subscribeSocketAction(object : ISocketActionListener { + override fun onSocketConnSuccess(socketAddress: SocketAddress?) { + LogUtil.e("socket连接成功,${HexUtil.formatHexString(mNeedSendMessage, true)}") + //发送 + EasySocket.getInstance().upMessage(mNeedSendMessage) + } + + override fun onSocketConnFail(socketAddress: SocketAddress?, isNeedReconnect: Boolean) { + LogUtil.e("socket连接失败,是否需要重连:$isNeedReconnect") + replyBleResult(1, null) + } + + override fun onSocketDisconnect( + socketAddress: SocketAddress?, isNeedReconnect: Boolean + ) { + LogUtil.e("socket断开连接,是否需要重连:$isNeedReconnect") + } + + override fun onSocketResponse( + socketAddress: SocketAddress?, originReadData: OriginReadData? + ) { + LogUtil.d("socket监听器收到对象数据=" + originReadData?.bodyString) + } + + override fun onSocketResponse(socketAddress: SocketAddress?, readData: String?) { + LogUtil.d("socket监听器收到字符串数据=$readData") + } + + override fun onSocketResponse(socketAddress: SocketAddress?, readData: ByteArray?) { + val data = HexUtil.formatHexString(readData, true) + LogUtil.e("socket监听器收到字节数组数据=$data") + readData?.apply { + if (size > 16 && this[15] == (0x94).toByte()) { + replyBleResult(0, this) + } + } + } + }) + } + + private fun replyBleResult(result: Int, data: ByteArray?) { + SRBleUtil.instance.getConnectMacDevice(mMac)?.let { + SRBleUtil.instance.writeData( + it.bleDevice, SRBleCmdUtil.instance.setProxy(result, data) + ) + } + destroy() + } + + private fun destroy() { + try { + //destroyConnection()代表销毁整个连接状态,跟disconnect()不一样,如果此时要进行socket连接需要重新创建一个连接 + EasySocket.getInstance().destroyConnection() + //注销监听socket相关行为 + EasySocket.getInstance().defOptions.reconnectionManager.detach() + LogUtil.e("socket销毁连接") + } catch (e: Exception) { + LogUtil.e("socket销毁连接异常:${e.message}") + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/abbidot/tracker/util/bluetooth/SRBleCmdUtil.kt b/app/src/main/java/com/abbidot/tracker/util/bluetooth/SRBleCmdUtil.kt index d356d9e..585c604 100644 --- a/app/src/main/java/com/abbidot/tracker/util/bluetooth/SRBleCmdUtil.kt +++ b/app/src/main/java/com/abbidot/tracker/util/bluetooth/SRBleCmdUtil.kt @@ -146,7 +146,7 @@ class SRBleCmdUtil private constructor() { * 绑定设备 */ fun bindDevice(): ByteArray { - val byteArray = byteArrayOf(0x01, CMD_WRITE.toByte(),0x02,0,0) + val byteArray = byteArrayOf(0x01, CMD_WRITE.toByte(), 0x02, 0, 0) return getCrc8Cmd(byteArray) } @@ -374,5 +374,15 @@ class SRBleCmdUtil private constructor() { byteArray = byteArray.plus(longTo4ByteArray((lat * 1000000).toLong())) return getCrc8Cmd(byteArray) } + + fun setProxy(result: Int, data: ByteArray?): ByteArray { + if (null == data) { + return getCrc8Cmd(byteArrayOf(0x24, result.toByte(), 0)) + } else { + var byteArray = byteArrayOf(0x24, result.toByte(), data.size.toByte()) + byteArray = byteArray.plus(data) + return getCrc8Cmd(byteArray) + } + } } diff --git a/app/src/main/java/com/abbidot/tracker/util/bluetooth/SRBleUtil.kt b/app/src/main/java/com/abbidot/tracker/util/bluetooth/SRBleUtil.kt index 1a92f2e..bba2a23 100644 --- a/app/src/main/java/com/abbidot/tracker/util/bluetooth/SRBleUtil.kt +++ b/app/src/main/java/com/abbidot/tracker/util/bluetooth/SRBleUtil.kt @@ -17,6 +17,8 @@ import com.abbidot.baselibrary.util.AppUtils import com.abbidot.baselibrary.util.LogUtil import com.abbidot.tracker.bean.BleTrackDeviceBean import com.abbidot.tracker.bean.ReceiveDeviceData +import com.abbidot.tracker.util.SocketUtilManage +import com.abbidot.tracker.util.SocketUtilManageV2 import com.abbidot.tracker.util.Util import com.clj.fastble.BleManager import com.clj.fastble.callback.BleGattCallback @@ -45,6 +47,7 @@ class SRBleUtil private constructor() { //人为停止扫描设备,扫描中断 var isScanInterrupt = false + private var mSocketUtilManage: SocketUtilManageV2? = null /** * Bluetooth_Base_UUID定义为 00000000-0000-1000-8000-00805F9B34FB @@ -229,6 +232,10 @@ class SRBleUtil private constructor() { } else if (data0 == 0x23 && data1 == 0x00) { LogUtil.e("${bleDevice.mac},获取手机定位") XEventBus.post(EventName.BleGetLocation, bleDevice.mac) + } else if (data0 == 0x24) { + LogUtil.e("${bleDevice.mac},蓝牙透传消息") + if (null == mSocketUtilManage) mSocketUtilManage = SocketUtilManageV2() + mSocketUtilManage?.initEasySocket(mContext!!, bleDevice.mac, data) } else { val deviceData = ReceiveDeviceData(bleDevice, data, bleDevice.mac) XEventBus.post(EventName.DeviceReceiveData, deviceData) diff --git a/app/src/main/java/com/abbidot/tracker/vm/MapViewModel.kt b/app/src/main/java/com/abbidot/tracker/vm/MapViewModel.kt index 4cae142..e4bd030 100644 --- a/app/src/main/java/com/abbidot/tracker/vm/MapViewModel.kt +++ b/app/src/main/java/com/abbidot/tracker/vm/MapViewModel.kt @@ -454,7 +454,8 @@ class MapViewModel : ViewModel() { R.drawable.icon_device_sleep_image, 0, 0, 0 ) it.text = String.format( - context.getString(R.string.txt_fully_asleep), forTime(updateTime) + context.getString(R.string.txt_fully_asleep), + getTimeDifference(updateTime * 1000, System.currentTimeMillis()) ) ViewUtil.instance.viewShow(closeBtn) } else if (powerSwitch == ConstantInt.Type0) { @@ -495,14 +496,34 @@ class MapViewModel : ViewModel() { } } - private fun forTime(timestamp: Long): String { - val durationMillis = - if (timestamp < 1000000000000) System.currentTimeMillis() - timestamp * 1000 - else System.currentTimeMillis() - timestamp - val hours = TimeUnit.MILLISECONDS.toHours(durationMillis) - val minutes = - TimeUnit.MILLISECONDS.toMinutes(durationMillis) - TimeUnit.HOURS.toMinutes(hours) - val timeStr = if (hours > 0) "${hours}h ${minutes}m" else "${minutes}m" + private fun getTimeDifference(startMillis: Long, endMillis: Long): String { + var diff = endMillis - startMillis + val days = TimeUnit.MILLISECONDS.toDays(diff) + diff -= TimeUnit.DAYS.toMillis(days) + + val hours = TimeUnit.MILLISECONDS.toHours(diff) + diff -= TimeUnit.HOURS.toMillis(hours) + + val minutes = TimeUnit.MILLISECONDS.toMinutes(diff) + var timeStr: String + if (days > 0) { + timeStr = if (days > 1) { + "$days days" + } else { + "$days day" + } + if (hours > 0) { + timeStr += " ${hours}h" + } + } else { + if (hours > 0) { + timeStr = "${hours}h" + if (minutes > 0) timeStr += " ${minutes}m" + } else { + timeStr = if (minutes > 0) "${minutes}m" + else "1m" + } + } return timeStr }