diff --git a/app/build.gradle b/app/build.gradle
index c9b11ec..1a81160 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -77,7 +77,7 @@
dependencies {
//基础依赖库
- implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1'
+ implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.3'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
//Google官方授权框架
diff --git a/app/build.gradle b/app/build.gradle
index c9b11ec..1a81160 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -77,7 +77,7 @@
dependencies {
//基础依赖库
- implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1'
+ implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.3'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
//Google官方授权框架
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2f152d8..5c645f0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -91,7 +91,6 @@
android:resource="@xml/file_paths" />
-
diff --git a/app/build.gradle b/app/build.gradle
index c9b11ec..1a81160 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -77,7 +77,7 @@
dependencies {
//基础依赖库
- implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1'
+ implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.3'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
//Google官方授权框架
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2f152d8..5c645f0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -91,7 +91,6 @@
android:resource="@xml/file_paths" />
-
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
index 6cb496c..e5fe1f5 100644
--- a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
@@ -1,6 +1,7 @@
package com.casic.common.detector.gd.base
import android.app.Application
+import android.util.Log
import com.casic.common.detector.gd.greendao.DaoMaster
import com.casic.common.detector.gd.greendao.DaoSession
import com.casic.common.detector.gd.uart.SerialPort
@@ -52,6 +53,7 @@
//千寻报文数据下发串口号
add(SerialPort(File("/dev/ttyS1"), 9600, 0))
}
+ Log.d(kTag, "onCreate: 已初始化 ${serialPorts.size} 个串口")
} catch (e: SecurityException) {
"您没有串口的读写权限!".show(this)
} catch (e: IOException) {
diff --git a/app/build.gradle b/app/build.gradle
index c9b11ec..1a81160 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -77,7 +77,7 @@
dependencies {
//基础依赖库
- implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1'
+ implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.3'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
//Google官方授权框架
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2f152d8..5c645f0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -91,7 +91,6 @@
android:resource="@xml/file_paths" />
-
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
index 6cb496c..e5fe1f5 100644
--- a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
@@ -1,6 +1,7 @@
package com.casic.common.detector.gd.base
import android.app.Application
+import android.util.Log
import com.casic.common.detector.gd.greendao.DaoMaster
import com.casic.common.detector.gd.greendao.DaoSession
import com.casic.common.detector.gd.uart.SerialPort
@@ -52,6 +53,7 @@
//千寻报文数据下发串口号
add(SerialPort(File("/dev/ttyS1"), 9600, 0))
}
+ Log.d(kTag, "onCreate: 已初始化 ${serialPorts.size} 个串口")
} catch (e: SecurityException) {
"您没有串口的读写权限!".show(this)
} catch (e: IOException) {
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
new file mode 100644
index 0000000..08b3e19
--- /dev/null
+++ b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
@@ -0,0 +1,204 @@
+package com.casic.common.detector.gd.base
+
+import android.os.Bundle
+import android.os.Handler
+import android.os.Message
+import android.util.Log
+import androidx.appcompat.app.AppCompatActivity
+import androidx.viewbinding.ViewBinding
+import com.casic.common.detector.gd.utils.CurrentSegment
+import com.casic.common.detector.gd.utils.GpioManager
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import java.io.IOException
+import java.util.Timer
+import java.util.TimerTask
+import java.util.concurrent.atomic.AtomicInteger
+
+abstract class SerialPortActivity : AppCompatActivity(), Handler.Callback {
+
+ private val kTag = "SerialPortActivity"
+ private val taskTimer by lazy { Timer() }
+ private val weakReferenceHandler by lazy { WeakReferenceHandler(this) }
+
+ //输出流
+ private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
+
+ //输入流
+ private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
+ private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
+
+ private var segment: CurrentSegment? = null
+
+ protected lateinit var binding: VB
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = initViewBinding()
+ setContentView(binding.root)
+ setupTopBarLayout()
+ initOnCreate(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = firstInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = lastInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+ }
+
+ /**
+ * 初始化ViewBinding
+ */
+ abstract fun initViewBinding(): VB
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initOnCreate(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ abstract fun onDataReceived(buffer: ByteArray, segment: CurrentSegment)
+
+ override fun handleMessage(msg: Message): Boolean {
+ if (msg.what == 2025012001) {
+ val bytes = msg.obj as ByteArray
+ if (segment == null) {
+ return true
+ }
+ Log.d(kTag, "$segment - ${bytes.contentToString()}")
+ onDataReceived(bytes, segment!!)
+ }
+ return true
+ }
+
+ private var readMarkerIdTask: TimerTask? = null
+ private var searchMarkerTask: TimerTask? = null
+
+ fun readMarkerId() {
+ this.segment = CurrentSegment.InstallMarker
+ readMarkerIdTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(readMarkerIdTask, 0, 300)
+ }
+
+ fun detectDepth(tag: Char) {
+ this.segment = CurrentSegment.DetectDepth
+ outStream.write('3'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write(tag.code)
+ outStream.flush()
+ }
+
+ fun updateSegment(segment: CurrentSegment) {
+ this.segment = segment
+ }
+
+ fun searchMarker(segment: CurrentSegment) {
+ this.segment = segment
+ searchMarkerTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write('6'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(searchMarkerTask, 0, 300)
+ }
+
+ /***************************************************************************************/
+ private val gpioManager by lazy { GpioManager() }
+
+ /**
+ * 读取数据 1
+ * 暂停读取 0
+ * */
+ private val gpioState = AtomicInteger(0)
+ fun openSerialPort() {
+ if (gpioState.get() != 1) {
+ gpioManager.setGpioHigh("18")
+ gpioState.set(1)
+ Log.d(kTag, "openSerialPort: 调高串口电位")
+ } else {
+ Log.d(kTag, "openSerialPort: 已经是高电位,直接读数据")
+ }
+ }
+
+ fun closeSerialPort() {
+ if (segment != null) {
+ segment = null
+ }
+ readMarkerIdTask?.cancel()
+ searchMarkerTask?.cancel()
+ if (gpioState.get() == 0) {
+ Log.d(kTag, "closeSerialPort: 已经是低电位,不响应")
+ return
+ }
+ // 降低串口电位
+ gpioManager.setGpioLow("18")
+ gpioState.set(0)
+ Log.d(kTag, "closeSerialPort: 降低串口电位")
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ closeSerialPort()
+ }
+}
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index c9b11ec..1a81160 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -77,7 +77,7 @@
dependencies {
//基础依赖库
- implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1'
+ implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.3'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
//Google官方授权框架
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2f152d8..5c645f0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -91,7 +91,6 @@
android:resource="@xml/file_paths" />
-
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
index 6cb496c..e5fe1f5 100644
--- a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
@@ -1,6 +1,7 @@
package com.casic.common.detector.gd.base
import android.app.Application
+import android.util.Log
import com.casic.common.detector.gd.greendao.DaoMaster
import com.casic.common.detector.gd.greendao.DaoSession
import com.casic.common.detector.gd.uart.SerialPort
@@ -52,6 +53,7 @@
//千寻报文数据下发串口号
add(SerialPort(File("/dev/ttyS1"), 9600, 0))
}
+ Log.d(kTag, "onCreate: 已初始化 ${serialPorts.size} 个串口")
} catch (e: SecurityException) {
"您没有串口的读写权限!".show(this)
} catch (e: IOException) {
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
new file mode 100644
index 0000000..08b3e19
--- /dev/null
+++ b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
@@ -0,0 +1,204 @@
+package com.casic.common.detector.gd.base
+
+import android.os.Bundle
+import android.os.Handler
+import android.os.Message
+import android.util.Log
+import androidx.appcompat.app.AppCompatActivity
+import androidx.viewbinding.ViewBinding
+import com.casic.common.detector.gd.utils.CurrentSegment
+import com.casic.common.detector.gd.utils.GpioManager
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import java.io.IOException
+import java.util.Timer
+import java.util.TimerTask
+import java.util.concurrent.atomic.AtomicInteger
+
+abstract class SerialPortActivity : AppCompatActivity(), Handler.Callback {
+
+ private val kTag = "SerialPortActivity"
+ private val taskTimer by lazy { Timer() }
+ private val weakReferenceHandler by lazy { WeakReferenceHandler(this) }
+
+ //输出流
+ private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
+
+ //输入流
+ private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
+ private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
+
+ private var segment: CurrentSegment? = null
+
+ protected lateinit var binding: VB
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = initViewBinding()
+ setContentView(binding.root)
+ setupTopBarLayout()
+ initOnCreate(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = firstInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = lastInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+ }
+
+ /**
+ * 初始化ViewBinding
+ */
+ abstract fun initViewBinding(): VB
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initOnCreate(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ abstract fun onDataReceived(buffer: ByteArray, segment: CurrentSegment)
+
+ override fun handleMessage(msg: Message): Boolean {
+ if (msg.what == 2025012001) {
+ val bytes = msg.obj as ByteArray
+ if (segment == null) {
+ return true
+ }
+ Log.d(kTag, "$segment - ${bytes.contentToString()}")
+ onDataReceived(bytes, segment!!)
+ }
+ return true
+ }
+
+ private var readMarkerIdTask: TimerTask? = null
+ private var searchMarkerTask: TimerTask? = null
+
+ fun readMarkerId() {
+ this.segment = CurrentSegment.InstallMarker
+ readMarkerIdTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(readMarkerIdTask, 0, 300)
+ }
+
+ fun detectDepth(tag: Char) {
+ this.segment = CurrentSegment.DetectDepth
+ outStream.write('3'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write(tag.code)
+ outStream.flush()
+ }
+
+ fun updateSegment(segment: CurrentSegment) {
+ this.segment = segment
+ }
+
+ fun searchMarker(segment: CurrentSegment) {
+ this.segment = segment
+ searchMarkerTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write('6'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(searchMarkerTask, 0, 300)
+ }
+
+ /***************************************************************************************/
+ private val gpioManager by lazy { GpioManager() }
+
+ /**
+ * 读取数据 1
+ * 暂停读取 0
+ * */
+ private val gpioState = AtomicInteger(0)
+ fun openSerialPort() {
+ if (gpioState.get() != 1) {
+ gpioManager.setGpioHigh("18")
+ gpioState.set(1)
+ Log.d(kTag, "openSerialPort: 调高串口电位")
+ } else {
+ Log.d(kTag, "openSerialPort: 已经是高电位,直接读数据")
+ }
+ }
+
+ fun closeSerialPort() {
+ if (segment != null) {
+ segment = null
+ }
+ readMarkerIdTask?.cancel()
+ searchMarkerTask?.cancel()
+ if (gpioState.get() == 0) {
+ Log.d(kTag, "closeSerialPort: 已经是低电位,不响应")
+ return
+ }
+ // 降低串口电位
+ gpioManager.setGpioLow("18")
+ gpioState.set(0)
+ Log.d(kTag, "closeSerialPort: 降低串口电位")
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ closeSerialPort()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
index 442189e..5c3ee01 100644
--- a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
@@ -1,42 +1,20 @@
package com.casic.common.detector.gd.extensions
-import android.util.Log
-
/**
* 因为数据频率很高,而且每一帧数据至少有一个信号值,如果有多个信号强度值,取平均值
*
* [78, 53, 49, 55, 51]
*
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
* */
fun ByteArray.toSignalStrength(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var strength = 0
+ for (byte in dataBytes) {
+ strength = strength * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return strength
}
/**
@@ -44,32 +22,13 @@
*
* [48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
*
- * [48, 48, 48, 56, 56, 57, 49, 48, 55, 51, 48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
- *
* */
fun ByteArray.toMarkerId(): String {
- //判断数据合理性
- val validBytes = if (this.size % 10 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 10) * 10
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ val id = this.map { it.toInt().toChar() }.joinToString("")
+ if (id.matches("-?\\d+".toRegex())) {
+ return id
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 10) {
- // 每10个字节取一次数据转为ASCII
- val tempBytes = validBytes.sliceArray(i until minOf(i + 10, validBytes.size))
- val string = tempBytes.map { it.toInt().toChar() }.joinToString("")
- if (string.matches("-?\\d+".toRegex())) {
- list.add(string)
- } else {
- Log.d("kTag", "toDeviceCode: 编号解析失败")
- }
- }
- return list.last()
+ return ""
}
/**
@@ -77,31 +36,14 @@
*
* [83, 48, 48, 48, 57]
*
- * [83, 48, 48, 48, 57, 83, 48, 48, 48, 57]
* */
fun ByteArray.toBuryDepth(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var depth = 0
+ for (byte in dataBytes) {
+ depth = depth * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return depth
}
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index c9b11ec..1a81160 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -77,7 +77,7 @@
dependencies {
//基础依赖库
- implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1'
+ implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.3'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
//Google官方授权框架
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2f152d8..5c645f0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -91,7 +91,6 @@
android:resource="@xml/file_paths" />
-
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
index 6cb496c..e5fe1f5 100644
--- a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
@@ -1,6 +1,7 @@
package com.casic.common.detector.gd.base
import android.app.Application
+import android.util.Log
import com.casic.common.detector.gd.greendao.DaoMaster
import com.casic.common.detector.gd.greendao.DaoSession
import com.casic.common.detector.gd.uart.SerialPort
@@ -52,6 +53,7 @@
//千寻报文数据下发串口号
add(SerialPort(File("/dev/ttyS1"), 9600, 0))
}
+ Log.d(kTag, "onCreate: 已初始化 ${serialPorts.size} 个串口")
} catch (e: SecurityException) {
"您没有串口的读写权限!".show(this)
} catch (e: IOException) {
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
new file mode 100644
index 0000000..08b3e19
--- /dev/null
+++ b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
@@ -0,0 +1,204 @@
+package com.casic.common.detector.gd.base
+
+import android.os.Bundle
+import android.os.Handler
+import android.os.Message
+import android.util.Log
+import androidx.appcompat.app.AppCompatActivity
+import androidx.viewbinding.ViewBinding
+import com.casic.common.detector.gd.utils.CurrentSegment
+import com.casic.common.detector.gd.utils.GpioManager
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import java.io.IOException
+import java.util.Timer
+import java.util.TimerTask
+import java.util.concurrent.atomic.AtomicInteger
+
+abstract class SerialPortActivity : AppCompatActivity(), Handler.Callback {
+
+ private val kTag = "SerialPortActivity"
+ private val taskTimer by lazy { Timer() }
+ private val weakReferenceHandler by lazy { WeakReferenceHandler(this) }
+
+ //输出流
+ private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
+
+ //输入流
+ private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
+ private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
+
+ private var segment: CurrentSegment? = null
+
+ protected lateinit var binding: VB
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = initViewBinding()
+ setContentView(binding.root)
+ setupTopBarLayout()
+ initOnCreate(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = firstInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = lastInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+ }
+
+ /**
+ * 初始化ViewBinding
+ */
+ abstract fun initViewBinding(): VB
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initOnCreate(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ abstract fun onDataReceived(buffer: ByteArray, segment: CurrentSegment)
+
+ override fun handleMessage(msg: Message): Boolean {
+ if (msg.what == 2025012001) {
+ val bytes = msg.obj as ByteArray
+ if (segment == null) {
+ return true
+ }
+ Log.d(kTag, "$segment - ${bytes.contentToString()}")
+ onDataReceived(bytes, segment!!)
+ }
+ return true
+ }
+
+ private var readMarkerIdTask: TimerTask? = null
+ private var searchMarkerTask: TimerTask? = null
+
+ fun readMarkerId() {
+ this.segment = CurrentSegment.InstallMarker
+ readMarkerIdTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(readMarkerIdTask, 0, 300)
+ }
+
+ fun detectDepth(tag: Char) {
+ this.segment = CurrentSegment.DetectDepth
+ outStream.write('3'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write(tag.code)
+ outStream.flush()
+ }
+
+ fun updateSegment(segment: CurrentSegment) {
+ this.segment = segment
+ }
+
+ fun searchMarker(segment: CurrentSegment) {
+ this.segment = segment
+ searchMarkerTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write('6'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(searchMarkerTask, 0, 300)
+ }
+
+ /***************************************************************************************/
+ private val gpioManager by lazy { GpioManager() }
+
+ /**
+ * 读取数据 1
+ * 暂停读取 0
+ * */
+ private val gpioState = AtomicInteger(0)
+ fun openSerialPort() {
+ if (gpioState.get() != 1) {
+ gpioManager.setGpioHigh("18")
+ gpioState.set(1)
+ Log.d(kTag, "openSerialPort: 调高串口电位")
+ } else {
+ Log.d(kTag, "openSerialPort: 已经是高电位,直接读数据")
+ }
+ }
+
+ fun closeSerialPort() {
+ if (segment != null) {
+ segment = null
+ }
+ readMarkerIdTask?.cancel()
+ searchMarkerTask?.cancel()
+ if (gpioState.get() == 0) {
+ Log.d(kTag, "closeSerialPort: 已经是低电位,不响应")
+ return
+ }
+ // 降低串口电位
+ gpioManager.setGpioLow("18")
+ gpioState.set(0)
+ Log.d(kTag, "closeSerialPort: 降低串口电位")
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ closeSerialPort()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
index 442189e..5c3ee01 100644
--- a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
@@ -1,42 +1,20 @@
package com.casic.common.detector.gd.extensions
-import android.util.Log
-
/**
* 因为数据频率很高,而且每一帧数据至少有一个信号值,如果有多个信号强度值,取平均值
*
* [78, 53, 49, 55, 51]
*
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
* */
fun ByteArray.toSignalStrength(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var strength = 0
+ for (byte in dataBytes) {
+ strength = strength * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return strength
}
/**
@@ -44,32 +22,13 @@
*
* [48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
*
- * [48, 48, 48, 56, 56, 57, 49, 48, 55, 51, 48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
- *
* */
fun ByteArray.toMarkerId(): String {
- //判断数据合理性
- val validBytes = if (this.size % 10 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 10) * 10
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ val id = this.map { it.toInt().toChar() }.joinToString("")
+ if (id.matches("-?\\d+".toRegex())) {
+ return id
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 10) {
- // 每10个字节取一次数据转为ASCII
- val tempBytes = validBytes.sliceArray(i until minOf(i + 10, validBytes.size))
- val string = tempBytes.map { it.toInt().toChar() }.joinToString("")
- if (string.matches("-?\\d+".toRegex())) {
- list.add(string)
- } else {
- Log.d("kTag", "toDeviceCode: 编号解析失败")
- }
- }
- return list.last()
+ return ""
}
/**
@@ -77,31 +36,14 @@
*
* [83, 48, 48, 48, 57]
*
- * [83, 48, 48, 48, 57, 83, 48, 48, 48, 57]
* */
fun ByteArray.toBuryDepth(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var depth = 0
+ for (byte in dataBytes) {
+ depth = depth * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return depth
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt b/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
deleted file mode 100644
index 76cf583..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
+++ /dev/null
@@ -1,136 +0,0 @@
-package com.casic.common.detector.gd.service
-
-import android.app.Service
-import android.content.Intent
-import android.os.Binder
-import android.os.IBinder
-import android.util.Log
-import com.casic.common.detector.gd.base.BaseApplication
-import com.casic.common.detector.gd.utils.CurrentSegment
-import com.casic.common.detector.gd.utils.LocaleConstant
-import com.casic.common.detector.gd.utils.RuntimeCache
-import com.casic.common.detector.gd.view.InstallMarkerActivity
-import com.casic.common.detector.gd.view.MainActivity
-import com.casic.common.detector.gd.view.SearchMarkerActivity
-import java.io.IOException
-import java.io.InputStream
-import java.util.concurrent.Executors
-import java.util.concurrent.TimeUnit
-
-class SerialPortService : Service() {
-
- private val kTag = "SerialPortService"
- private val sendExecutor = Executors.newFixedThreadPool(5)
- private val readExecutor = Executors.newSingleThreadScheduledExecutor()
-
- //输出流
- private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
-
- //输入流
- private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
- private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
-
- override fun onCreate() {
- super.onCreate()
- try {
- // 使用单线程调度器读取数据
- readExecutor.scheduleAtFixedRate({
- readData(firstInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
-
- readExecutor.scheduleAtFixedRate({
- readData(lastInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- private fun readData(inputStream: InputStream) {
- try {
- val buffer = ByteArray(1024)
- var bytesRead: Int
- while (inputStream.available() > 0) {
- bytesRead = inputStream.read(buffer)
- if (bytesRead > 0) {
- when (RuntimeCache.currentSegment) {
- CurrentSegment.DetectMarkerDepth -> {
- //深度
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.DETECT_MARKER_DEPTH
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.InstallMarker -> {
- //安装点
- InstallMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.INSTALL_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.FreeInspection -> {
- //自由巡检
- MainActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.FREE_INSPECTION
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.SearchMarker -> {
- //搜索标识器
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.SEARCH_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- else -> {
- val bytes = buffer.copyOf(bytesRead)
- Log.d(kTag, "空状态,不处理 ===> ${bytes.contentToString()}")
- }
- }
- }
- }
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- fun writeCommand(vararg command: Char) {
- Log.d(kTag, "writeCommand: ${command.contentToString()}")
- if (command.size == 1) {
- sendExecutor.submit {
- outStream.write(command.first().code)
- outStream.flush()
- }
- } else {
- command.forEach {
- sendExecutor.submit {
- outStream.write(it.code)
- outStream.flush()
- }
- Thread.sleep(1000)
- }
- }
- }
-
- override fun onBind(intent: Intent?): IBinder {
- return ServiceBinder()
- }
-
- inner class ServiceBinder : Binder() {
- fun getSerialPortService(): SerialPortService {
- return this@SerialPortService
- }
- }
-}
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index c9b11ec..1a81160 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -77,7 +77,7 @@
dependencies {
//基础依赖库
- implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1'
+ implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.3'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
//Google官方授权框架
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2f152d8..5c645f0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -91,7 +91,6 @@
android:resource="@xml/file_paths" />
-
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
index 6cb496c..e5fe1f5 100644
--- a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
@@ -1,6 +1,7 @@
package com.casic.common.detector.gd.base
import android.app.Application
+import android.util.Log
import com.casic.common.detector.gd.greendao.DaoMaster
import com.casic.common.detector.gd.greendao.DaoSession
import com.casic.common.detector.gd.uart.SerialPort
@@ -52,6 +53,7 @@
//千寻报文数据下发串口号
add(SerialPort(File("/dev/ttyS1"), 9600, 0))
}
+ Log.d(kTag, "onCreate: 已初始化 ${serialPorts.size} 个串口")
} catch (e: SecurityException) {
"您没有串口的读写权限!".show(this)
} catch (e: IOException) {
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
new file mode 100644
index 0000000..08b3e19
--- /dev/null
+++ b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
@@ -0,0 +1,204 @@
+package com.casic.common.detector.gd.base
+
+import android.os.Bundle
+import android.os.Handler
+import android.os.Message
+import android.util.Log
+import androidx.appcompat.app.AppCompatActivity
+import androidx.viewbinding.ViewBinding
+import com.casic.common.detector.gd.utils.CurrentSegment
+import com.casic.common.detector.gd.utils.GpioManager
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import java.io.IOException
+import java.util.Timer
+import java.util.TimerTask
+import java.util.concurrent.atomic.AtomicInteger
+
+abstract class SerialPortActivity : AppCompatActivity(), Handler.Callback {
+
+ private val kTag = "SerialPortActivity"
+ private val taskTimer by lazy { Timer() }
+ private val weakReferenceHandler by lazy { WeakReferenceHandler(this) }
+
+ //输出流
+ private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
+
+ //输入流
+ private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
+ private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
+
+ private var segment: CurrentSegment? = null
+
+ protected lateinit var binding: VB
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = initViewBinding()
+ setContentView(binding.root)
+ setupTopBarLayout()
+ initOnCreate(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = firstInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = lastInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+ }
+
+ /**
+ * 初始化ViewBinding
+ */
+ abstract fun initViewBinding(): VB
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initOnCreate(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ abstract fun onDataReceived(buffer: ByteArray, segment: CurrentSegment)
+
+ override fun handleMessage(msg: Message): Boolean {
+ if (msg.what == 2025012001) {
+ val bytes = msg.obj as ByteArray
+ if (segment == null) {
+ return true
+ }
+ Log.d(kTag, "$segment - ${bytes.contentToString()}")
+ onDataReceived(bytes, segment!!)
+ }
+ return true
+ }
+
+ private var readMarkerIdTask: TimerTask? = null
+ private var searchMarkerTask: TimerTask? = null
+
+ fun readMarkerId() {
+ this.segment = CurrentSegment.InstallMarker
+ readMarkerIdTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(readMarkerIdTask, 0, 300)
+ }
+
+ fun detectDepth(tag: Char) {
+ this.segment = CurrentSegment.DetectDepth
+ outStream.write('3'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write(tag.code)
+ outStream.flush()
+ }
+
+ fun updateSegment(segment: CurrentSegment) {
+ this.segment = segment
+ }
+
+ fun searchMarker(segment: CurrentSegment) {
+ this.segment = segment
+ searchMarkerTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write('6'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(searchMarkerTask, 0, 300)
+ }
+
+ /***************************************************************************************/
+ private val gpioManager by lazy { GpioManager() }
+
+ /**
+ * 读取数据 1
+ * 暂停读取 0
+ * */
+ private val gpioState = AtomicInteger(0)
+ fun openSerialPort() {
+ if (gpioState.get() != 1) {
+ gpioManager.setGpioHigh("18")
+ gpioState.set(1)
+ Log.d(kTag, "openSerialPort: 调高串口电位")
+ } else {
+ Log.d(kTag, "openSerialPort: 已经是高电位,直接读数据")
+ }
+ }
+
+ fun closeSerialPort() {
+ if (segment != null) {
+ segment = null
+ }
+ readMarkerIdTask?.cancel()
+ searchMarkerTask?.cancel()
+ if (gpioState.get() == 0) {
+ Log.d(kTag, "closeSerialPort: 已经是低电位,不响应")
+ return
+ }
+ // 降低串口电位
+ gpioManager.setGpioLow("18")
+ gpioState.set(0)
+ Log.d(kTag, "closeSerialPort: 降低串口电位")
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ closeSerialPort()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
index 442189e..5c3ee01 100644
--- a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
@@ -1,42 +1,20 @@
package com.casic.common.detector.gd.extensions
-import android.util.Log
-
/**
* 因为数据频率很高,而且每一帧数据至少有一个信号值,如果有多个信号强度值,取平均值
*
* [78, 53, 49, 55, 51]
*
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
* */
fun ByteArray.toSignalStrength(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var strength = 0
+ for (byte in dataBytes) {
+ strength = strength * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return strength
}
/**
@@ -44,32 +22,13 @@
*
* [48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
*
- * [48, 48, 48, 56, 56, 57, 49, 48, 55, 51, 48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
- *
* */
fun ByteArray.toMarkerId(): String {
- //判断数据合理性
- val validBytes = if (this.size % 10 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 10) * 10
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ val id = this.map { it.toInt().toChar() }.joinToString("")
+ if (id.matches("-?\\d+".toRegex())) {
+ return id
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 10) {
- // 每10个字节取一次数据转为ASCII
- val tempBytes = validBytes.sliceArray(i until minOf(i + 10, validBytes.size))
- val string = tempBytes.map { it.toInt().toChar() }.joinToString("")
- if (string.matches("-?\\d+".toRegex())) {
- list.add(string)
- } else {
- Log.d("kTag", "toDeviceCode: 编号解析失败")
- }
- }
- return list.last()
+ return ""
}
/**
@@ -77,31 +36,14 @@
*
* [83, 48, 48, 48, 57]
*
- * [83, 48, 48, 48, 57, 83, 48, 48, 48, 57]
* */
fun ByteArray.toBuryDepth(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var depth = 0
+ for (byte in dataBytes) {
+ depth = depth * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return depth
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt b/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
deleted file mode 100644
index 76cf583..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
+++ /dev/null
@@ -1,136 +0,0 @@
-package com.casic.common.detector.gd.service
-
-import android.app.Service
-import android.content.Intent
-import android.os.Binder
-import android.os.IBinder
-import android.util.Log
-import com.casic.common.detector.gd.base.BaseApplication
-import com.casic.common.detector.gd.utils.CurrentSegment
-import com.casic.common.detector.gd.utils.LocaleConstant
-import com.casic.common.detector.gd.utils.RuntimeCache
-import com.casic.common.detector.gd.view.InstallMarkerActivity
-import com.casic.common.detector.gd.view.MainActivity
-import com.casic.common.detector.gd.view.SearchMarkerActivity
-import java.io.IOException
-import java.io.InputStream
-import java.util.concurrent.Executors
-import java.util.concurrent.TimeUnit
-
-class SerialPortService : Service() {
-
- private val kTag = "SerialPortService"
- private val sendExecutor = Executors.newFixedThreadPool(5)
- private val readExecutor = Executors.newSingleThreadScheduledExecutor()
-
- //输出流
- private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
-
- //输入流
- private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
- private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
-
- override fun onCreate() {
- super.onCreate()
- try {
- // 使用单线程调度器读取数据
- readExecutor.scheduleAtFixedRate({
- readData(firstInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
-
- readExecutor.scheduleAtFixedRate({
- readData(lastInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- private fun readData(inputStream: InputStream) {
- try {
- val buffer = ByteArray(1024)
- var bytesRead: Int
- while (inputStream.available() > 0) {
- bytesRead = inputStream.read(buffer)
- if (bytesRead > 0) {
- when (RuntimeCache.currentSegment) {
- CurrentSegment.DetectMarkerDepth -> {
- //深度
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.DETECT_MARKER_DEPTH
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.InstallMarker -> {
- //安装点
- InstallMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.INSTALL_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.FreeInspection -> {
- //自由巡检
- MainActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.FREE_INSPECTION
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.SearchMarker -> {
- //搜索标识器
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.SEARCH_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- else -> {
- val bytes = buffer.copyOf(bytesRead)
- Log.d(kTag, "空状态,不处理 ===> ${bytes.contentToString()}")
- }
- }
- }
- }
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- fun writeCommand(vararg command: Char) {
- Log.d(kTag, "writeCommand: ${command.contentToString()}")
- if (command.size == 1) {
- sendExecutor.submit {
- outStream.write(command.first().code)
- outStream.flush()
- }
- } else {
- command.forEach {
- sendExecutor.submit {
- outStream.write(it.code)
- outStream.flush()
- }
- Thread.sleep(1000)
- }
- }
- }
-
- override fun onBind(intent: Intent?): IBinder {
- return ServiceBinder()
- }
-
- inner class ServiceBinder : Binder() {
- fun getSerialPortService(): SerialPortService {
- return this@SerialPortService
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt b/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
index 0606b72..9efa097 100644
--- a/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
@@ -1,23 +1,23 @@
package com.casic.common.detector.gd.utils
-sealed class CurrentSegment {
+enum class CurrentSegment {
/**
* 安装标识器
* */
- object InstallMarker : CurrentSegment()
+ InstallMarker,
/**
* 自由巡检
* */
- object FreeInspection : CurrentSegment()
+ FreeInspection,
/**
* 搜索标识器
* */
- object SearchMarker : CurrentSegment()
+ SearchMarker,
/**
* 探测标识器深度
* */
- object DetectMarkerDepth : CurrentSegment()
+ DetectDepth
}
diff --git a/app/build.gradle b/app/build.gradle
index c9b11ec..1a81160 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -77,7 +77,7 @@
dependencies {
//基础依赖库
- implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1'
+ implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.3'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
//Google官方授权框架
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2f152d8..5c645f0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -91,7 +91,6 @@
android:resource="@xml/file_paths" />
-
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
index 6cb496c..e5fe1f5 100644
--- a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
@@ -1,6 +1,7 @@
package com.casic.common.detector.gd.base
import android.app.Application
+import android.util.Log
import com.casic.common.detector.gd.greendao.DaoMaster
import com.casic.common.detector.gd.greendao.DaoSession
import com.casic.common.detector.gd.uart.SerialPort
@@ -52,6 +53,7 @@
//千寻报文数据下发串口号
add(SerialPort(File("/dev/ttyS1"), 9600, 0))
}
+ Log.d(kTag, "onCreate: 已初始化 ${serialPorts.size} 个串口")
} catch (e: SecurityException) {
"您没有串口的读写权限!".show(this)
} catch (e: IOException) {
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
new file mode 100644
index 0000000..08b3e19
--- /dev/null
+++ b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
@@ -0,0 +1,204 @@
+package com.casic.common.detector.gd.base
+
+import android.os.Bundle
+import android.os.Handler
+import android.os.Message
+import android.util.Log
+import androidx.appcompat.app.AppCompatActivity
+import androidx.viewbinding.ViewBinding
+import com.casic.common.detector.gd.utils.CurrentSegment
+import com.casic.common.detector.gd.utils.GpioManager
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import java.io.IOException
+import java.util.Timer
+import java.util.TimerTask
+import java.util.concurrent.atomic.AtomicInteger
+
+abstract class SerialPortActivity : AppCompatActivity(), Handler.Callback {
+
+ private val kTag = "SerialPortActivity"
+ private val taskTimer by lazy { Timer() }
+ private val weakReferenceHandler by lazy { WeakReferenceHandler(this) }
+
+ //输出流
+ private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
+
+ //输入流
+ private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
+ private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
+
+ private var segment: CurrentSegment? = null
+
+ protected lateinit var binding: VB
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = initViewBinding()
+ setContentView(binding.root)
+ setupTopBarLayout()
+ initOnCreate(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = firstInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = lastInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+ }
+
+ /**
+ * 初始化ViewBinding
+ */
+ abstract fun initViewBinding(): VB
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initOnCreate(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ abstract fun onDataReceived(buffer: ByteArray, segment: CurrentSegment)
+
+ override fun handleMessage(msg: Message): Boolean {
+ if (msg.what == 2025012001) {
+ val bytes = msg.obj as ByteArray
+ if (segment == null) {
+ return true
+ }
+ Log.d(kTag, "$segment - ${bytes.contentToString()}")
+ onDataReceived(bytes, segment!!)
+ }
+ return true
+ }
+
+ private var readMarkerIdTask: TimerTask? = null
+ private var searchMarkerTask: TimerTask? = null
+
+ fun readMarkerId() {
+ this.segment = CurrentSegment.InstallMarker
+ readMarkerIdTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(readMarkerIdTask, 0, 300)
+ }
+
+ fun detectDepth(tag: Char) {
+ this.segment = CurrentSegment.DetectDepth
+ outStream.write('3'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write(tag.code)
+ outStream.flush()
+ }
+
+ fun updateSegment(segment: CurrentSegment) {
+ this.segment = segment
+ }
+
+ fun searchMarker(segment: CurrentSegment) {
+ this.segment = segment
+ searchMarkerTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write('6'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(searchMarkerTask, 0, 300)
+ }
+
+ /***************************************************************************************/
+ private val gpioManager by lazy { GpioManager() }
+
+ /**
+ * 读取数据 1
+ * 暂停读取 0
+ * */
+ private val gpioState = AtomicInteger(0)
+ fun openSerialPort() {
+ if (gpioState.get() != 1) {
+ gpioManager.setGpioHigh("18")
+ gpioState.set(1)
+ Log.d(kTag, "openSerialPort: 调高串口电位")
+ } else {
+ Log.d(kTag, "openSerialPort: 已经是高电位,直接读数据")
+ }
+ }
+
+ fun closeSerialPort() {
+ if (segment != null) {
+ segment = null
+ }
+ readMarkerIdTask?.cancel()
+ searchMarkerTask?.cancel()
+ if (gpioState.get() == 0) {
+ Log.d(kTag, "closeSerialPort: 已经是低电位,不响应")
+ return
+ }
+ // 降低串口电位
+ gpioManager.setGpioLow("18")
+ gpioState.set(0)
+ Log.d(kTag, "closeSerialPort: 降低串口电位")
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ closeSerialPort()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
index 442189e..5c3ee01 100644
--- a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
@@ -1,42 +1,20 @@
package com.casic.common.detector.gd.extensions
-import android.util.Log
-
/**
* 因为数据频率很高,而且每一帧数据至少有一个信号值,如果有多个信号强度值,取平均值
*
* [78, 53, 49, 55, 51]
*
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
* */
fun ByteArray.toSignalStrength(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var strength = 0
+ for (byte in dataBytes) {
+ strength = strength * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return strength
}
/**
@@ -44,32 +22,13 @@
*
* [48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
*
- * [48, 48, 48, 56, 56, 57, 49, 48, 55, 51, 48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
- *
* */
fun ByteArray.toMarkerId(): String {
- //判断数据合理性
- val validBytes = if (this.size % 10 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 10) * 10
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ val id = this.map { it.toInt().toChar() }.joinToString("")
+ if (id.matches("-?\\d+".toRegex())) {
+ return id
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 10) {
- // 每10个字节取一次数据转为ASCII
- val tempBytes = validBytes.sliceArray(i until minOf(i + 10, validBytes.size))
- val string = tempBytes.map { it.toInt().toChar() }.joinToString("")
- if (string.matches("-?\\d+".toRegex())) {
- list.add(string)
- } else {
- Log.d("kTag", "toDeviceCode: 编号解析失败")
- }
- }
- return list.last()
+ return ""
}
/**
@@ -77,31 +36,14 @@
*
* [83, 48, 48, 48, 57]
*
- * [83, 48, 48, 48, 57, 83, 48, 48, 48, 57]
* */
fun ByteArray.toBuryDepth(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var depth = 0
+ for (byte in dataBytes) {
+ depth = depth * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return depth
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt b/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
deleted file mode 100644
index 76cf583..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
+++ /dev/null
@@ -1,136 +0,0 @@
-package com.casic.common.detector.gd.service
-
-import android.app.Service
-import android.content.Intent
-import android.os.Binder
-import android.os.IBinder
-import android.util.Log
-import com.casic.common.detector.gd.base.BaseApplication
-import com.casic.common.detector.gd.utils.CurrentSegment
-import com.casic.common.detector.gd.utils.LocaleConstant
-import com.casic.common.detector.gd.utils.RuntimeCache
-import com.casic.common.detector.gd.view.InstallMarkerActivity
-import com.casic.common.detector.gd.view.MainActivity
-import com.casic.common.detector.gd.view.SearchMarkerActivity
-import java.io.IOException
-import java.io.InputStream
-import java.util.concurrent.Executors
-import java.util.concurrent.TimeUnit
-
-class SerialPortService : Service() {
-
- private val kTag = "SerialPortService"
- private val sendExecutor = Executors.newFixedThreadPool(5)
- private val readExecutor = Executors.newSingleThreadScheduledExecutor()
-
- //输出流
- private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
-
- //输入流
- private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
- private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
-
- override fun onCreate() {
- super.onCreate()
- try {
- // 使用单线程调度器读取数据
- readExecutor.scheduleAtFixedRate({
- readData(firstInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
-
- readExecutor.scheduleAtFixedRate({
- readData(lastInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- private fun readData(inputStream: InputStream) {
- try {
- val buffer = ByteArray(1024)
- var bytesRead: Int
- while (inputStream.available() > 0) {
- bytesRead = inputStream.read(buffer)
- if (bytesRead > 0) {
- when (RuntimeCache.currentSegment) {
- CurrentSegment.DetectMarkerDepth -> {
- //深度
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.DETECT_MARKER_DEPTH
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.InstallMarker -> {
- //安装点
- InstallMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.INSTALL_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.FreeInspection -> {
- //自由巡检
- MainActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.FREE_INSPECTION
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.SearchMarker -> {
- //搜索标识器
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.SEARCH_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- else -> {
- val bytes = buffer.copyOf(bytesRead)
- Log.d(kTag, "空状态,不处理 ===> ${bytes.contentToString()}")
- }
- }
- }
- }
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- fun writeCommand(vararg command: Char) {
- Log.d(kTag, "writeCommand: ${command.contentToString()}")
- if (command.size == 1) {
- sendExecutor.submit {
- outStream.write(command.first().code)
- outStream.flush()
- }
- } else {
- command.forEach {
- sendExecutor.submit {
- outStream.write(it.code)
- outStream.flush()
- }
- Thread.sleep(1000)
- }
- }
- }
-
- override fun onBind(intent: Intent?): IBinder {
- return ServiceBinder()
- }
-
- inner class ServiceBinder : Binder() {
- fun getSerialPortService(): SerialPortService {
- return this@SerialPortService
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt b/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
index 0606b72..9efa097 100644
--- a/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
@@ -1,23 +1,23 @@
package com.casic.common.detector.gd.utils
-sealed class CurrentSegment {
+enum class CurrentSegment {
/**
* 安装标识器
* */
- object InstallMarker : CurrentSegment()
+ InstallMarker,
/**
* 自由巡检
* */
- object FreeInspection : CurrentSegment()
+ FreeInspection,
/**
* 搜索标识器
* */
- object SearchMarker : CurrentSegment()
+ SearchMarker,
/**
* 探测标识器深度
* */
- object DetectMarkerDepth : CurrentSegment()
+ DetectDepth
}
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt
deleted file mode 100644
index c9151a8..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt
+++ /dev/null
@@ -1,150 +0,0 @@
-package com.casic.common.detector.gd.utils
-
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.SupervisorJob
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import okhttp3.Call
-import okhttp3.Callback
-import okhttp3.OkHttpClient
-import okhttp3.Request
-import okhttp3.Response
-import java.io.File
-import java.io.IOException
-import java.util.concurrent.atomic.AtomicBoolean
-
-class FileDownloadManager(builder: Builder) {
-
- private val httpClient by lazy { OkHttpClient() }
-
- class Builder {
- lateinit var url: String
- lateinit var suffix: String
- lateinit var directory: File
- lateinit var downloadListener: OnFileDownloadListener
-
- /**
- * 文件下载地址
- * */
- fun setDownloadFileSource(url: String): Builder {
- this.url = url
- return this
- }
-
- /**
- * 文件后缀
- * 如:apk等
- * */
- fun setFileSuffix(suffix: String): Builder {
- this.suffix = if (suffix.contains(".")) {
- //去掉前缀的点
- suffix.drop(1)
- } else {
- suffix
- }
- return this
- }
-
- /**
- * 文件保存的地址
- * */
- fun setFileSaveDirectory(directory: File): Builder {
- this.directory = directory
- return this
- }
-
- /**
- * 设置文件下载回调监听
- * */
- fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder {
- this.downloadListener = downloadListener
- return this
- }
-
- fun build(): FileDownloadManager {
- if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) {
- throw IllegalStateException("All properties must be initialized before building.")
- }
- return FileDownloadManager(this)
- }
- }
-
- private val url = builder.url
- private val suffix = builder.suffix
- private val directory = builder.directory
- private val listener = builder.downloadListener
-
- /**
- * 开始下载
- * */
- fun start() {
- val job = SupervisorJob()
- val scope = CoroutineScope(Dispatchers.Main + job)
-
- val request = Request.Builder().get().url(url).build()
- val newCall = httpClient.newCall(request)
- val isExecuting = AtomicBoolean(false)
-
- /**
- * 如果已被加入下载队列,则取消之前的,重新下载
- */
- if (isExecuting.getAndSet(true)) {
- newCall.cancel()
- }
-
- //异步下载文件
- newCall.enqueue(object : Callback {
- override fun onFailure(call: Call, e: IOException) {
- scope.launch(Dispatchers.Main) {
- listener.onFailed(e)
- }
- }
-
- override fun onResponse(call: Call, response: Response) {
- scope.launch(Dispatchers.IO) {
- val body = response.body
- if (body == null) {
- listener.onFailed(IOException("Response body is null"))
- throw IOException("Response body is null")
- } else {
- val inputStream = body.byteStream()
- val fileSize = body.contentLength()
-
- if (fileSize <= 0) {
- throw IllegalArgumentException("Invalid file size")
- }
- listener.onDownloadStart(fileSize)
-
- val file = File(directory, "${System.currentTimeMillis()}.${suffix}")
- file.outputStream().use { fos ->
- val buffer = ByteArray(2048)
- var sum = 0L
- var read: Int
- while (inputStream.read(buffer).also { read = it } != -1) {
- fos.write(buffer, 0, read)
- sum += read.toLong()
- withContext(Dispatchers.Main) {
- listener.onProgressChanged(sum)
- }
- }
- }
-
- withContext(Dispatchers.Main) {
- listener.onDownloadEnd(file)
- }
-
- job.cancel()
- }
- }
- }
- })
- }
-
- interface OnFileDownloadListener {
- fun onDownloadStart(total: Long)
- fun onProgressChanged(progress: Long)
- fun onDownloadEnd(file: File)
- fun onFailed(t: Throwable)
- }
-}
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index c9b11ec..1a81160 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -77,7 +77,7 @@
dependencies {
//基础依赖库
- implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1'
+ implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.3'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
//Google官方授权框架
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2f152d8..5c645f0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -91,7 +91,6 @@
android:resource="@xml/file_paths" />
-
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
index 6cb496c..e5fe1f5 100644
--- a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
@@ -1,6 +1,7 @@
package com.casic.common.detector.gd.base
import android.app.Application
+import android.util.Log
import com.casic.common.detector.gd.greendao.DaoMaster
import com.casic.common.detector.gd.greendao.DaoSession
import com.casic.common.detector.gd.uart.SerialPort
@@ -52,6 +53,7 @@
//千寻报文数据下发串口号
add(SerialPort(File("/dev/ttyS1"), 9600, 0))
}
+ Log.d(kTag, "onCreate: 已初始化 ${serialPorts.size} 个串口")
} catch (e: SecurityException) {
"您没有串口的读写权限!".show(this)
} catch (e: IOException) {
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
new file mode 100644
index 0000000..08b3e19
--- /dev/null
+++ b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
@@ -0,0 +1,204 @@
+package com.casic.common.detector.gd.base
+
+import android.os.Bundle
+import android.os.Handler
+import android.os.Message
+import android.util.Log
+import androidx.appcompat.app.AppCompatActivity
+import androidx.viewbinding.ViewBinding
+import com.casic.common.detector.gd.utils.CurrentSegment
+import com.casic.common.detector.gd.utils.GpioManager
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import java.io.IOException
+import java.util.Timer
+import java.util.TimerTask
+import java.util.concurrent.atomic.AtomicInteger
+
+abstract class SerialPortActivity : AppCompatActivity(), Handler.Callback {
+
+ private val kTag = "SerialPortActivity"
+ private val taskTimer by lazy { Timer() }
+ private val weakReferenceHandler by lazy { WeakReferenceHandler(this) }
+
+ //输出流
+ private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
+
+ //输入流
+ private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
+ private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
+
+ private var segment: CurrentSegment? = null
+
+ protected lateinit var binding: VB
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = initViewBinding()
+ setContentView(binding.root)
+ setupTopBarLayout()
+ initOnCreate(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = firstInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = lastInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+ }
+
+ /**
+ * 初始化ViewBinding
+ */
+ abstract fun initViewBinding(): VB
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initOnCreate(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ abstract fun onDataReceived(buffer: ByteArray, segment: CurrentSegment)
+
+ override fun handleMessage(msg: Message): Boolean {
+ if (msg.what == 2025012001) {
+ val bytes = msg.obj as ByteArray
+ if (segment == null) {
+ return true
+ }
+ Log.d(kTag, "$segment - ${bytes.contentToString()}")
+ onDataReceived(bytes, segment!!)
+ }
+ return true
+ }
+
+ private var readMarkerIdTask: TimerTask? = null
+ private var searchMarkerTask: TimerTask? = null
+
+ fun readMarkerId() {
+ this.segment = CurrentSegment.InstallMarker
+ readMarkerIdTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(readMarkerIdTask, 0, 300)
+ }
+
+ fun detectDepth(tag: Char) {
+ this.segment = CurrentSegment.DetectDepth
+ outStream.write('3'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write(tag.code)
+ outStream.flush()
+ }
+
+ fun updateSegment(segment: CurrentSegment) {
+ this.segment = segment
+ }
+
+ fun searchMarker(segment: CurrentSegment) {
+ this.segment = segment
+ searchMarkerTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write('6'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(searchMarkerTask, 0, 300)
+ }
+
+ /***************************************************************************************/
+ private val gpioManager by lazy { GpioManager() }
+
+ /**
+ * 读取数据 1
+ * 暂停读取 0
+ * */
+ private val gpioState = AtomicInteger(0)
+ fun openSerialPort() {
+ if (gpioState.get() != 1) {
+ gpioManager.setGpioHigh("18")
+ gpioState.set(1)
+ Log.d(kTag, "openSerialPort: 调高串口电位")
+ } else {
+ Log.d(kTag, "openSerialPort: 已经是高电位,直接读数据")
+ }
+ }
+
+ fun closeSerialPort() {
+ if (segment != null) {
+ segment = null
+ }
+ readMarkerIdTask?.cancel()
+ searchMarkerTask?.cancel()
+ if (gpioState.get() == 0) {
+ Log.d(kTag, "closeSerialPort: 已经是低电位,不响应")
+ return
+ }
+ // 降低串口电位
+ gpioManager.setGpioLow("18")
+ gpioState.set(0)
+ Log.d(kTag, "closeSerialPort: 降低串口电位")
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ closeSerialPort()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
index 442189e..5c3ee01 100644
--- a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
@@ -1,42 +1,20 @@
package com.casic.common.detector.gd.extensions
-import android.util.Log
-
/**
* 因为数据频率很高,而且每一帧数据至少有一个信号值,如果有多个信号强度值,取平均值
*
* [78, 53, 49, 55, 51]
*
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
* */
fun ByteArray.toSignalStrength(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var strength = 0
+ for (byte in dataBytes) {
+ strength = strength * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return strength
}
/**
@@ -44,32 +22,13 @@
*
* [48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
*
- * [48, 48, 48, 56, 56, 57, 49, 48, 55, 51, 48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
- *
* */
fun ByteArray.toMarkerId(): String {
- //判断数据合理性
- val validBytes = if (this.size % 10 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 10) * 10
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ val id = this.map { it.toInt().toChar() }.joinToString("")
+ if (id.matches("-?\\d+".toRegex())) {
+ return id
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 10) {
- // 每10个字节取一次数据转为ASCII
- val tempBytes = validBytes.sliceArray(i until minOf(i + 10, validBytes.size))
- val string = tempBytes.map { it.toInt().toChar() }.joinToString("")
- if (string.matches("-?\\d+".toRegex())) {
- list.add(string)
- } else {
- Log.d("kTag", "toDeviceCode: 编号解析失败")
- }
- }
- return list.last()
+ return ""
}
/**
@@ -77,31 +36,14 @@
*
* [83, 48, 48, 48, 57]
*
- * [83, 48, 48, 48, 57, 83, 48, 48, 48, 57]
* */
fun ByteArray.toBuryDepth(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var depth = 0
+ for (byte in dataBytes) {
+ depth = depth * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return depth
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt b/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
deleted file mode 100644
index 76cf583..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
+++ /dev/null
@@ -1,136 +0,0 @@
-package com.casic.common.detector.gd.service
-
-import android.app.Service
-import android.content.Intent
-import android.os.Binder
-import android.os.IBinder
-import android.util.Log
-import com.casic.common.detector.gd.base.BaseApplication
-import com.casic.common.detector.gd.utils.CurrentSegment
-import com.casic.common.detector.gd.utils.LocaleConstant
-import com.casic.common.detector.gd.utils.RuntimeCache
-import com.casic.common.detector.gd.view.InstallMarkerActivity
-import com.casic.common.detector.gd.view.MainActivity
-import com.casic.common.detector.gd.view.SearchMarkerActivity
-import java.io.IOException
-import java.io.InputStream
-import java.util.concurrent.Executors
-import java.util.concurrent.TimeUnit
-
-class SerialPortService : Service() {
-
- private val kTag = "SerialPortService"
- private val sendExecutor = Executors.newFixedThreadPool(5)
- private val readExecutor = Executors.newSingleThreadScheduledExecutor()
-
- //输出流
- private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
-
- //输入流
- private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
- private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
-
- override fun onCreate() {
- super.onCreate()
- try {
- // 使用单线程调度器读取数据
- readExecutor.scheduleAtFixedRate({
- readData(firstInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
-
- readExecutor.scheduleAtFixedRate({
- readData(lastInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- private fun readData(inputStream: InputStream) {
- try {
- val buffer = ByteArray(1024)
- var bytesRead: Int
- while (inputStream.available() > 0) {
- bytesRead = inputStream.read(buffer)
- if (bytesRead > 0) {
- when (RuntimeCache.currentSegment) {
- CurrentSegment.DetectMarkerDepth -> {
- //深度
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.DETECT_MARKER_DEPTH
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.InstallMarker -> {
- //安装点
- InstallMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.INSTALL_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.FreeInspection -> {
- //自由巡检
- MainActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.FREE_INSPECTION
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.SearchMarker -> {
- //搜索标识器
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.SEARCH_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- else -> {
- val bytes = buffer.copyOf(bytesRead)
- Log.d(kTag, "空状态,不处理 ===> ${bytes.contentToString()}")
- }
- }
- }
- }
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- fun writeCommand(vararg command: Char) {
- Log.d(kTag, "writeCommand: ${command.contentToString()}")
- if (command.size == 1) {
- sendExecutor.submit {
- outStream.write(command.first().code)
- outStream.flush()
- }
- } else {
- command.forEach {
- sendExecutor.submit {
- outStream.write(it.code)
- outStream.flush()
- }
- Thread.sleep(1000)
- }
- }
- }
-
- override fun onBind(intent: Intent?): IBinder {
- return ServiceBinder()
- }
-
- inner class ServiceBinder : Binder() {
- fun getSerialPortService(): SerialPortService {
- return this@SerialPortService
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt b/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
index 0606b72..9efa097 100644
--- a/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
@@ -1,23 +1,23 @@
package com.casic.common.detector.gd.utils
-sealed class CurrentSegment {
+enum class CurrentSegment {
/**
* 安装标识器
* */
- object InstallMarker : CurrentSegment()
+ InstallMarker,
/**
* 自由巡检
* */
- object FreeInspection : CurrentSegment()
+ FreeInspection,
/**
* 搜索标识器
* */
- object SearchMarker : CurrentSegment()
+ SearchMarker,
/**
* 探测标识器深度
* */
- object DetectMarkerDepth : CurrentSegment()
+ DetectDepth
}
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt
deleted file mode 100644
index c9151a8..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt
+++ /dev/null
@@ -1,150 +0,0 @@
-package com.casic.common.detector.gd.utils
-
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.SupervisorJob
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import okhttp3.Call
-import okhttp3.Callback
-import okhttp3.OkHttpClient
-import okhttp3.Request
-import okhttp3.Response
-import java.io.File
-import java.io.IOException
-import java.util.concurrent.atomic.AtomicBoolean
-
-class FileDownloadManager(builder: Builder) {
-
- private val httpClient by lazy { OkHttpClient() }
-
- class Builder {
- lateinit var url: String
- lateinit var suffix: String
- lateinit var directory: File
- lateinit var downloadListener: OnFileDownloadListener
-
- /**
- * 文件下载地址
- * */
- fun setDownloadFileSource(url: String): Builder {
- this.url = url
- return this
- }
-
- /**
- * 文件后缀
- * 如:apk等
- * */
- fun setFileSuffix(suffix: String): Builder {
- this.suffix = if (suffix.contains(".")) {
- //去掉前缀的点
- suffix.drop(1)
- } else {
- suffix
- }
- return this
- }
-
- /**
- * 文件保存的地址
- * */
- fun setFileSaveDirectory(directory: File): Builder {
- this.directory = directory
- return this
- }
-
- /**
- * 设置文件下载回调监听
- * */
- fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder {
- this.downloadListener = downloadListener
- return this
- }
-
- fun build(): FileDownloadManager {
- if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) {
- throw IllegalStateException("All properties must be initialized before building.")
- }
- return FileDownloadManager(this)
- }
- }
-
- private val url = builder.url
- private val suffix = builder.suffix
- private val directory = builder.directory
- private val listener = builder.downloadListener
-
- /**
- * 开始下载
- * */
- fun start() {
- val job = SupervisorJob()
- val scope = CoroutineScope(Dispatchers.Main + job)
-
- val request = Request.Builder().get().url(url).build()
- val newCall = httpClient.newCall(request)
- val isExecuting = AtomicBoolean(false)
-
- /**
- * 如果已被加入下载队列,则取消之前的,重新下载
- */
- if (isExecuting.getAndSet(true)) {
- newCall.cancel()
- }
-
- //异步下载文件
- newCall.enqueue(object : Callback {
- override fun onFailure(call: Call, e: IOException) {
- scope.launch(Dispatchers.Main) {
- listener.onFailed(e)
- }
- }
-
- override fun onResponse(call: Call, response: Response) {
- scope.launch(Dispatchers.IO) {
- val body = response.body
- if (body == null) {
- listener.onFailed(IOException("Response body is null"))
- throw IOException("Response body is null")
- } else {
- val inputStream = body.byteStream()
- val fileSize = body.contentLength()
-
- if (fileSize <= 0) {
- throw IllegalArgumentException("Invalid file size")
- }
- listener.onDownloadStart(fileSize)
-
- val file = File(directory, "${System.currentTimeMillis()}.${suffix}")
- file.outputStream().use { fos ->
- val buffer = ByteArray(2048)
- var sum = 0L
- var read: Int
- while (inputStream.read(buffer).also { read = it } != -1) {
- fos.write(buffer, 0, read)
- sum += read.toLong()
- withContext(Dispatchers.Main) {
- listener.onProgressChanged(sum)
- }
- }
- }
-
- withContext(Dispatchers.Main) {
- listener.onDownloadEnd(file)
- }
-
- job.cancel()
- }
- }
- }
- })
- }
-
- interface OnFileDownloadListener {
- fun onDownloadStart(total: Long)
- fun onProgressChanged(progress: Long)
- fun onDownloadEnd(file: File)
- fun onFailed(t: Throwable)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt b/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
index 2334680..c658924 100644
--- a/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
@@ -14,10 +14,6 @@
const val PERMISSIONS_CODE = 999
const val MAX_DISTANCE = 5.5f //表盘最大显示距离
- const val FREE_INSPECTION = 20250101
- const val INSTALL_MARKER = 20250102
- const val DETECT_MARKER_DEPTH = 20250103
- const val SEARCH_MARKER = 20250104
const val AUTO_SAVE = "AUTO_SAVE"
const val USER_ACCOUNT = "USER_ACCOUNT"
diff --git a/app/build.gradle b/app/build.gradle
index c9b11ec..1a81160 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -77,7 +77,7 @@
dependencies {
//基础依赖库
- implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1'
+ implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.3'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
//Google官方授权框架
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2f152d8..5c645f0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -91,7 +91,6 @@
android:resource="@xml/file_paths" />
-
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
index 6cb496c..e5fe1f5 100644
--- a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
@@ -1,6 +1,7 @@
package com.casic.common.detector.gd.base
import android.app.Application
+import android.util.Log
import com.casic.common.detector.gd.greendao.DaoMaster
import com.casic.common.detector.gd.greendao.DaoSession
import com.casic.common.detector.gd.uart.SerialPort
@@ -52,6 +53,7 @@
//千寻报文数据下发串口号
add(SerialPort(File("/dev/ttyS1"), 9600, 0))
}
+ Log.d(kTag, "onCreate: 已初始化 ${serialPorts.size} 个串口")
} catch (e: SecurityException) {
"您没有串口的读写权限!".show(this)
} catch (e: IOException) {
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
new file mode 100644
index 0000000..08b3e19
--- /dev/null
+++ b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
@@ -0,0 +1,204 @@
+package com.casic.common.detector.gd.base
+
+import android.os.Bundle
+import android.os.Handler
+import android.os.Message
+import android.util.Log
+import androidx.appcompat.app.AppCompatActivity
+import androidx.viewbinding.ViewBinding
+import com.casic.common.detector.gd.utils.CurrentSegment
+import com.casic.common.detector.gd.utils.GpioManager
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import java.io.IOException
+import java.util.Timer
+import java.util.TimerTask
+import java.util.concurrent.atomic.AtomicInteger
+
+abstract class SerialPortActivity : AppCompatActivity(), Handler.Callback {
+
+ private val kTag = "SerialPortActivity"
+ private val taskTimer by lazy { Timer() }
+ private val weakReferenceHandler by lazy { WeakReferenceHandler(this) }
+
+ //输出流
+ private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
+
+ //输入流
+ private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
+ private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
+
+ private var segment: CurrentSegment? = null
+
+ protected lateinit var binding: VB
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = initViewBinding()
+ setContentView(binding.root)
+ setupTopBarLayout()
+ initOnCreate(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = firstInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = lastInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+ }
+
+ /**
+ * 初始化ViewBinding
+ */
+ abstract fun initViewBinding(): VB
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initOnCreate(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ abstract fun onDataReceived(buffer: ByteArray, segment: CurrentSegment)
+
+ override fun handleMessage(msg: Message): Boolean {
+ if (msg.what == 2025012001) {
+ val bytes = msg.obj as ByteArray
+ if (segment == null) {
+ return true
+ }
+ Log.d(kTag, "$segment - ${bytes.contentToString()}")
+ onDataReceived(bytes, segment!!)
+ }
+ return true
+ }
+
+ private var readMarkerIdTask: TimerTask? = null
+ private var searchMarkerTask: TimerTask? = null
+
+ fun readMarkerId() {
+ this.segment = CurrentSegment.InstallMarker
+ readMarkerIdTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(readMarkerIdTask, 0, 300)
+ }
+
+ fun detectDepth(tag: Char) {
+ this.segment = CurrentSegment.DetectDepth
+ outStream.write('3'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write(tag.code)
+ outStream.flush()
+ }
+
+ fun updateSegment(segment: CurrentSegment) {
+ this.segment = segment
+ }
+
+ fun searchMarker(segment: CurrentSegment) {
+ this.segment = segment
+ searchMarkerTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write('6'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(searchMarkerTask, 0, 300)
+ }
+
+ /***************************************************************************************/
+ private val gpioManager by lazy { GpioManager() }
+
+ /**
+ * 读取数据 1
+ * 暂停读取 0
+ * */
+ private val gpioState = AtomicInteger(0)
+ fun openSerialPort() {
+ if (gpioState.get() != 1) {
+ gpioManager.setGpioHigh("18")
+ gpioState.set(1)
+ Log.d(kTag, "openSerialPort: 调高串口电位")
+ } else {
+ Log.d(kTag, "openSerialPort: 已经是高电位,直接读数据")
+ }
+ }
+
+ fun closeSerialPort() {
+ if (segment != null) {
+ segment = null
+ }
+ readMarkerIdTask?.cancel()
+ searchMarkerTask?.cancel()
+ if (gpioState.get() == 0) {
+ Log.d(kTag, "closeSerialPort: 已经是低电位,不响应")
+ return
+ }
+ // 降低串口电位
+ gpioManager.setGpioLow("18")
+ gpioState.set(0)
+ Log.d(kTag, "closeSerialPort: 降低串口电位")
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ closeSerialPort()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
index 442189e..5c3ee01 100644
--- a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
@@ -1,42 +1,20 @@
package com.casic.common.detector.gd.extensions
-import android.util.Log
-
/**
* 因为数据频率很高,而且每一帧数据至少有一个信号值,如果有多个信号强度值,取平均值
*
* [78, 53, 49, 55, 51]
*
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
* */
fun ByteArray.toSignalStrength(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var strength = 0
+ for (byte in dataBytes) {
+ strength = strength * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return strength
}
/**
@@ -44,32 +22,13 @@
*
* [48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
*
- * [48, 48, 48, 56, 56, 57, 49, 48, 55, 51, 48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
- *
* */
fun ByteArray.toMarkerId(): String {
- //判断数据合理性
- val validBytes = if (this.size % 10 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 10) * 10
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ val id = this.map { it.toInt().toChar() }.joinToString("")
+ if (id.matches("-?\\d+".toRegex())) {
+ return id
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 10) {
- // 每10个字节取一次数据转为ASCII
- val tempBytes = validBytes.sliceArray(i until minOf(i + 10, validBytes.size))
- val string = tempBytes.map { it.toInt().toChar() }.joinToString("")
- if (string.matches("-?\\d+".toRegex())) {
- list.add(string)
- } else {
- Log.d("kTag", "toDeviceCode: 编号解析失败")
- }
- }
- return list.last()
+ return ""
}
/**
@@ -77,31 +36,14 @@
*
* [83, 48, 48, 48, 57]
*
- * [83, 48, 48, 48, 57, 83, 48, 48, 48, 57]
* */
fun ByteArray.toBuryDepth(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var depth = 0
+ for (byte in dataBytes) {
+ depth = depth * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return depth
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt b/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
deleted file mode 100644
index 76cf583..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
+++ /dev/null
@@ -1,136 +0,0 @@
-package com.casic.common.detector.gd.service
-
-import android.app.Service
-import android.content.Intent
-import android.os.Binder
-import android.os.IBinder
-import android.util.Log
-import com.casic.common.detector.gd.base.BaseApplication
-import com.casic.common.detector.gd.utils.CurrentSegment
-import com.casic.common.detector.gd.utils.LocaleConstant
-import com.casic.common.detector.gd.utils.RuntimeCache
-import com.casic.common.detector.gd.view.InstallMarkerActivity
-import com.casic.common.detector.gd.view.MainActivity
-import com.casic.common.detector.gd.view.SearchMarkerActivity
-import java.io.IOException
-import java.io.InputStream
-import java.util.concurrent.Executors
-import java.util.concurrent.TimeUnit
-
-class SerialPortService : Service() {
-
- private val kTag = "SerialPortService"
- private val sendExecutor = Executors.newFixedThreadPool(5)
- private val readExecutor = Executors.newSingleThreadScheduledExecutor()
-
- //输出流
- private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
-
- //输入流
- private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
- private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
-
- override fun onCreate() {
- super.onCreate()
- try {
- // 使用单线程调度器读取数据
- readExecutor.scheduleAtFixedRate({
- readData(firstInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
-
- readExecutor.scheduleAtFixedRate({
- readData(lastInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- private fun readData(inputStream: InputStream) {
- try {
- val buffer = ByteArray(1024)
- var bytesRead: Int
- while (inputStream.available() > 0) {
- bytesRead = inputStream.read(buffer)
- if (bytesRead > 0) {
- when (RuntimeCache.currentSegment) {
- CurrentSegment.DetectMarkerDepth -> {
- //深度
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.DETECT_MARKER_DEPTH
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.InstallMarker -> {
- //安装点
- InstallMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.INSTALL_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.FreeInspection -> {
- //自由巡检
- MainActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.FREE_INSPECTION
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.SearchMarker -> {
- //搜索标识器
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.SEARCH_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- else -> {
- val bytes = buffer.copyOf(bytesRead)
- Log.d(kTag, "空状态,不处理 ===> ${bytes.contentToString()}")
- }
- }
- }
- }
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- fun writeCommand(vararg command: Char) {
- Log.d(kTag, "writeCommand: ${command.contentToString()}")
- if (command.size == 1) {
- sendExecutor.submit {
- outStream.write(command.first().code)
- outStream.flush()
- }
- } else {
- command.forEach {
- sendExecutor.submit {
- outStream.write(it.code)
- outStream.flush()
- }
- Thread.sleep(1000)
- }
- }
- }
-
- override fun onBind(intent: Intent?): IBinder {
- return ServiceBinder()
- }
-
- inner class ServiceBinder : Binder() {
- fun getSerialPortService(): SerialPortService {
- return this@SerialPortService
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt b/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
index 0606b72..9efa097 100644
--- a/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
@@ -1,23 +1,23 @@
package com.casic.common.detector.gd.utils
-sealed class CurrentSegment {
+enum class CurrentSegment {
/**
* 安装标识器
* */
- object InstallMarker : CurrentSegment()
+ InstallMarker,
/**
* 自由巡检
* */
- object FreeInspection : CurrentSegment()
+ FreeInspection,
/**
* 搜索标识器
* */
- object SearchMarker : CurrentSegment()
+ SearchMarker,
/**
* 探测标识器深度
* */
- object DetectMarkerDepth : CurrentSegment()
+ DetectDepth
}
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt
deleted file mode 100644
index c9151a8..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt
+++ /dev/null
@@ -1,150 +0,0 @@
-package com.casic.common.detector.gd.utils
-
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.SupervisorJob
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import okhttp3.Call
-import okhttp3.Callback
-import okhttp3.OkHttpClient
-import okhttp3.Request
-import okhttp3.Response
-import java.io.File
-import java.io.IOException
-import java.util.concurrent.atomic.AtomicBoolean
-
-class FileDownloadManager(builder: Builder) {
-
- private val httpClient by lazy { OkHttpClient() }
-
- class Builder {
- lateinit var url: String
- lateinit var suffix: String
- lateinit var directory: File
- lateinit var downloadListener: OnFileDownloadListener
-
- /**
- * 文件下载地址
- * */
- fun setDownloadFileSource(url: String): Builder {
- this.url = url
- return this
- }
-
- /**
- * 文件后缀
- * 如:apk等
- * */
- fun setFileSuffix(suffix: String): Builder {
- this.suffix = if (suffix.contains(".")) {
- //去掉前缀的点
- suffix.drop(1)
- } else {
- suffix
- }
- return this
- }
-
- /**
- * 文件保存的地址
- * */
- fun setFileSaveDirectory(directory: File): Builder {
- this.directory = directory
- return this
- }
-
- /**
- * 设置文件下载回调监听
- * */
- fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder {
- this.downloadListener = downloadListener
- return this
- }
-
- fun build(): FileDownloadManager {
- if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) {
- throw IllegalStateException("All properties must be initialized before building.")
- }
- return FileDownloadManager(this)
- }
- }
-
- private val url = builder.url
- private val suffix = builder.suffix
- private val directory = builder.directory
- private val listener = builder.downloadListener
-
- /**
- * 开始下载
- * */
- fun start() {
- val job = SupervisorJob()
- val scope = CoroutineScope(Dispatchers.Main + job)
-
- val request = Request.Builder().get().url(url).build()
- val newCall = httpClient.newCall(request)
- val isExecuting = AtomicBoolean(false)
-
- /**
- * 如果已被加入下载队列,则取消之前的,重新下载
- */
- if (isExecuting.getAndSet(true)) {
- newCall.cancel()
- }
-
- //异步下载文件
- newCall.enqueue(object : Callback {
- override fun onFailure(call: Call, e: IOException) {
- scope.launch(Dispatchers.Main) {
- listener.onFailed(e)
- }
- }
-
- override fun onResponse(call: Call, response: Response) {
- scope.launch(Dispatchers.IO) {
- val body = response.body
- if (body == null) {
- listener.onFailed(IOException("Response body is null"))
- throw IOException("Response body is null")
- } else {
- val inputStream = body.byteStream()
- val fileSize = body.contentLength()
-
- if (fileSize <= 0) {
- throw IllegalArgumentException("Invalid file size")
- }
- listener.onDownloadStart(fileSize)
-
- val file = File(directory, "${System.currentTimeMillis()}.${suffix}")
- file.outputStream().use { fos ->
- val buffer = ByteArray(2048)
- var sum = 0L
- var read: Int
- while (inputStream.read(buffer).also { read = it } != -1) {
- fos.write(buffer, 0, read)
- sum += read.toLong()
- withContext(Dispatchers.Main) {
- listener.onProgressChanged(sum)
- }
- }
- }
-
- withContext(Dispatchers.Main) {
- listener.onDownloadEnd(file)
- }
-
- job.cancel()
- }
- }
- }
- })
- }
-
- interface OnFileDownloadListener {
- fun onDownloadStart(total: Long)
- fun onProgressChanged(progress: Long)
- fun onDownloadEnd(file: File)
- fun onFailed(t: Throwable)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt b/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
index 2334680..c658924 100644
--- a/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
@@ -14,10 +14,6 @@
const val PERMISSIONS_CODE = 999
const val MAX_DISTANCE = 5.5f //表盘最大显示距离
- const val FREE_INSPECTION = 20250101
- const val INSTALL_MARKER = 20250102
- const val DETECT_MARKER_DEPTH = 20250103
- const val SEARCH_MARKER = 20250104
const val AUTO_SAVE = "AUTO_SAVE"
const val USER_ACCOUNT = "USER_ACCOUNT"
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt b/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt
deleted file mode 100644
index 104f971..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.casic.common.detector.gd.utils
-
-object RuntimeCache {
- var currentSegment: CurrentSegment? = null
-}
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index c9b11ec..1a81160 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -77,7 +77,7 @@
dependencies {
//基础依赖库
- implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1'
+ implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.3'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
//Google官方授权框架
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2f152d8..5c645f0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -91,7 +91,6 @@
android:resource="@xml/file_paths" />
-
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
index 6cb496c..e5fe1f5 100644
--- a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
@@ -1,6 +1,7 @@
package com.casic.common.detector.gd.base
import android.app.Application
+import android.util.Log
import com.casic.common.detector.gd.greendao.DaoMaster
import com.casic.common.detector.gd.greendao.DaoSession
import com.casic.common.detector.gd.uart.SerialPort
@@ -52,6 +53,7 @@
//千寻报文数据下发串口号
add(SerialPort(File("/dev/ttyS1"), 9600, 0))
}
+ Log.d(kTag, "onCreate: 已初始化 ${serialPorts.size} 个串口")
} catch (e: SecurityException) {
"您没有串口的读写权限!".show(this)
} catch (e: IOException) {
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
new file mode 100644
index 0000000..08b3e19
--- /dev/null
+++ b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
@@ -0,0 +1,204 @@
+package com.casic.common.detector.gd.base
+
+import android.os.Bundle
+import android.os.Handler
+import android.os.Message
+import android.util.Log
+import androidx.appcompat.app.AppCompatActivity
+import androidx.viewbinding.ViewBinding
+import com.casic.common.detector.gd.utils.CurrentSegment
+import com.casic.common.detector.gd.utils.GpioManager
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import java.io.IOException
+import java.util.Timer
+import java.util.TimerTask
+import java.util.concurrent.atomic.AtomicInteger
+
+abstract class SerialPortActivity : AppCompatActivity(), Handler.Callback {
+
+ private val kTag = "SerialPortActivity"
+ private val taskTimer by lazy { Timer() }
+ private val weakReferenceHandler by lazy { WeakReferenceHandler(this) }
+
+ //输出流
+ private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
+
+ //输入流
+ private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
+ private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
+
+ private var segment: CurrentSegment? = null
+
+ protected lateinit var binding: VB
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = initViewBinding()
+ setContentView(binding.root)
+ setupTopBarLayout()
+ initOnCreate(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = firstInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = lastInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+ }
+
+ /**
+ * 初始化ViewBinding
+ */
+ abstract fun initViewBinding(): VB
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initOnCreate(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ abstract fun onDataReceived(buffer: ByteArray, segment: CurrentSegment)
+
+ override fun handleMessage(msg: Message): Boolean {
+ if (msg.what == 2025012001) {
+ val bytes = msg.obj as ByteArray
+ if (segment == null) {
+ return true
+ }
+ Log.d(kTag, "$segment - ${bytes.contentToString()}")
+ onDataReceived(bytes, segment!!)
+ }
+ return true
+ }
+
+ private var readMarkerIdTask: TimerTask? = null
+ private var searchMarkerTask: TimerTask? = null
+
+ fun readMarkerId() {
+ this.segment = CurrentSegment.InstallMarker
+ readMarkerIdTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(readMarkerIdTask, 0, 300)
+ }
+
+ fun detectDepth(tag: Char) {
+ this.segment = CurrentSegment.DetectDepth
+ outStream.write('3'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write(tag.code)
+ outStream.flush()
+ }
+
+ fun updateSegment(segment: CurrentSegment) {
+ this.segment = segment
+ }
+
+ fun searchMarker(segment: CurrentSegment) {
+ this.segment = segment
+ searchMarkerTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write('6'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(searchMarkerTask, 0, 300)
+ }
+
+ /***************************************************************************************/
+ private val gpioManager by lazy { GpioManager() }
+
+ /**
+ * 读取数据 1
+ * 暂停读取 0
+ * */
+ private val gpioState = AtomicInteger(0)
+ fun openSerialPort() {
+ if (gpioState.get() != 1) {
+ gpioManager.setGpioHigh("18")
+ gpioState.set(1)
+ Log.d(kTag, "openSerialPort: 调高串口电位")
+ } else {
+ Log.d(kTag, "openSerialPort: 已经是高电位,直接读数据")
+ }
+ }
+
+ fun closeSerialPort() {
+ if (segment != null) {
+ segment = null
+ }
+ readMarkerIdTask?.cancel()
+ searchMarkerTask?.cancel()
+ if (gpioState.get() == 0) {
+ Log.d(kTag, "closeSerialPort: 已经是低电位,不响应")
+ return
+ }
+ // 降低串口电位
+ gpioManager.setGpioLow("18")
+ gpioState.set(0)
+ Log.d(kTag, "closeSerialPort: 降低串口电位")
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ closeSerialPort()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
index 442189e..5c3ee01 100644
--- a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
@@ -1,42 +1,20 @@
package com.casic.common.detector.gd.extensions
-import android.util.Log
-
/**
* 因为数据频率很高,而且每一帧数据至少有一个信号值,如果有多个信号强度值,取平均值
*
* [78, 53, 49, 55, 51]
*
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
* */
fun ByteArray.toSignalStrength(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var strength = 0
+ for (byte in dataBytes) {
+ strength = strength * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return strength
}
/**
@@ -44,32 +22,13 @@
*
* [48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
*
- * [48, 48, 48, 56, 56, 57, 49, 48, 55, 51, 48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
- *
* */
fun ByteArray.toMarkerId(): String {
- //判断数据合理性
- val validBytes = if (this.size % 10 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 10) * 10
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ val id = this.map { it.toInt().toChar() }.joinToString("")
+ if (id.matches("-?\\d+".toRegex())) {
+ return id
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 10) {
- // 每10个字节取一次数据转为ASCII
- val tempBytes = validBytes.sliceArray(i until minOf(i + 10, validBytes.size))
- val string = tempBytes.map { it.toInt().toChar() }.joinToString("")
- if (string.matches("-?\\d+".toRegex())) {
- list.add(string)
- } else {
- Log.d("kTag", "toDeviceCode: 编号解析失败")
- }
- }
- return list.last()
+ return ""
}
/**
@@ -77,31 +36,14 @@
*
* [83, 48, 48, 48, 57]
*
- * [83, 48, 48, 48, 57, 83, 48, 48, 48, 57]
* */
fun ByteArray.toBuryDepth(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var depth = 0
+ for (byte in dataBytes) {
+ depth = depth * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return depth
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt b/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
deleted file mode 100644
index 76cf583..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
+++ /dev/null
@@ -1,136 +0,0 @@
-package com.casic.common.detector.gd.service
-
-import android.app.Service
-import android.content.Intent
-import android.os.Binder
-import android.os.IBinder
-import android.util.Log
-import com.casic.common.detector.gd.base.BaseApplication
-import com.casic.common.detector.gd.utils.CurrentSegment
-import com.casic.common.detector.gd.utils.LocaleConstant
-import com.casic.common.detector.gd.utils.RuntimeCache
-import com.casic.common.detector.gd.view.InstallMarkerActivity
-import com.casic.common.detector.gd.view.MainActivity
-import com.casic.common.detector.gd.view.SearchMarkerActivity
-import java.io.IOException
-import java.io.InputStream
-import java.util.concurrent.Executors
-import java.util.concurrent.TimeUnit
-
-class SerialPortService : Service() {
-
- private val kTag = "SerialPortService"
- private val sendExecutor = Executors.newFixedThreadPool(5)
- private val readExecutor = Executors.newSingleThreadScheduledExecutor()
-
- //输出流
- private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
-
- //输入流
- private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
- private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
-
- override fun onCreate() {
- super.onCreate()
- try {
- // 使用单线程调度器读取数据
- readExecutor.scheduleAtFixedRate({
- readData(firstInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
-
- readExecutor.scheduleAtFixedRate({
- readData(lastInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- private fun readData(inputStream: InputStream) {
- try {
- val buffer = ByteArray(1024)
- var bytesRead: Int
- while (inputStream.available() > 0) {
- bytesRead = inputStream.read(buffer)
- if (bytesRead > 0) {
- when (RuntimeCache.currentSegment) {
- CurrentSegment.DetectMarkerDepth -> {
- //深度
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.DETECT_MARKER_DEPTH
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.InstallMarker -> {
- //安装点
- InstallMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.INSTALL_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.FreeInspection -> {
- //自由巡检
- MainActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.FREE_INSPECTION
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.SearchMarker -> {
- //搜索标识器
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.SEARCH_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- else -> {
- val bytes = buffer.copyOf(bytesRead)
- Log.d(kTag, "空状态,不处理 ===> ${bytes.contentToString()}")
- }
- }
- }
- }
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- fun writeCommand(vararg command: Char) {
- Log.d(kTag, "writeCommand: ${command.contentToString()}")
- if (command.size == 1) {
- sendExecutor.submit {
- outStream.write(command.first().code)
- outStream.flush()
- }
- } else {
- command.forEach {
- sendExecutor.submit {
- outStream.write(it.code)
- outStream.flush()
- }
- Thread.sleep(1000)
- }
- }
- }
-
- override fun onBind(intent: Intent?): IBinder {
- return ServiceBinder()
- }
-
- inner class ServiceBinder : Binder() {
- fun getSerialPortService(): SerialPortService {
- return this@SerialPortService
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt b/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
index 0606b72..9efa097 100644
--- a/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
@@ -1,23 +1,23 @@
package com.casic.common.detector.gd.utils
-sealed class CurrentSegment {
+enum class CurrentSegment {
/**
* 安装标识器
* */
- object InstallMarker : CurrentSegment()
+ InstallMarker,
/**
* 自由巡检
* */
- object FreeInspection : CurrentSegment()
+ FreeInspection,
/**
* 搜索标识器
* */
- object SearchMarker : CurrentSegment()
+ SearchMarker,
/**
* 探测标识器深度
* */
- object DetectMarkerDepth : CurrentSegment()
+ DetectDepth
}
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt
deleted file mode 100644
index c9151a8..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt
+++ /dev/null
@@ -1,150 +0,0 @@
-package com.casic.common.detector.gd.utils
-
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.SupervisorJob
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import okhttp3.Call
-import okhttp3.Callback
-import okhttp3.OkHttpClient
-import okhttp3.Request
-import okhttp3.Response
-import java.io.File
-import java.io.IOException
-import java.util.concurrent.atomic.AtomicBoolean
-
-class FileDownloadManager(builder: Builder) {
-
- private val httpClient by lazy { OkHttpClient() }
-
- class Builder {
- lateinit var url: String
- lateinit var suffix: String
- lateinit var directory: File
- lateinit var downloadListener: OnFileDownloadListener
-
- /**
- * 文件下载地址
- * */
- fun setDownloadFileSource(url: String): Builder {
- this.url = url
- return this
- }
-
- /**
- * 文件后缀
- * 如:apk等
- * */
- fun setFileSuffix(suffix: String): Builder {
- this.suffix = if (suffix.contains(".")) {
- //去掉前缀的点
- suffix.drop(1)
- } else {
- suffix
- }
- return this
- }
-
- /**
- * 文件保存的地址
- * */
- fun setFileSaveDirectory(directory: File): Builder {
- this.directory = directory
- return this
- }
-
- /**
- * 设置文件下载回调监听
- * */
- fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder {
- this.downloadListener = downloadListener
- return this
- }
-
- fun build(): FileDownloadManager {
- if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) {
- throw IllegalStateException("All properties must be initialized before building.")
- }
- return FileDownloadManager(this)
- }
- }
-
- private val url = builder.url
- private val suffix = builder.suffix
- private val directory = builder.directory
- private val listener = builder.downloadListener
-
- /**
- * 开始下载
- * */
- fun start() {
- val job = SupervisorJob()
- val scope = CoroutineScope(Dispatchers.Main + job)
-
- val request = Request.Builder().get().url(url).build()
- val newCall = httpClient.newCall(request)
- val isExecuting = AtomicBoolean(false)
-
- /**
- * 如果已被加入下载队列,则取消之前的,重新下载
- */
- if (isExecuting.getAndSet(true)) {
- newCall.cancel()
- }
-
- //异步下载文件
- newCall.enqueue(object : Callback {
- override fun onFailure(call: Call, e: IOException) {
- scope.launch(Dispatchers.Main) {
- listener.onFailed(e)
- }
- }
-
- override fun onResponse(call: Call, response: Response) {
- scope.launch(Dispatchers.IO) {
- val body = response.body
- if (body == null) {
- listener.onFailed(IOException("Response body is null"))
- throw IOException("Response body is null")
- } else {
- val inputStream = body.byteStream()
- val fileSize = body.contentLength()
-
- if (fileSize <= 0) {
- throw IllegalArgumentException("Invalid file size")
- }
- listener.onDownloadStart(fileSize)
-
- val file = File(directory, "${System.currentTimeMillis()}.${suffix}")
- file.outputStream().use { fos ->
- val buffer = ByteArray(2048)
- var sum = 0L
- var read: Int
- while (inputStream.read(buffer).also { read = it } != -1) {
- fos.write(buffer, 0, read)
- sum += read.toLong()
- withContext(Dispatchers.Main) {
- listener.onProgressChanged(sum)
- }
- }
- }
-
- withContext(Dispatchers.Main) {
- listener.onDownloadEnd(file)
- }
-
- job.cancel()
- }
- }
- }
- })
- }
-
- interface OnFileDownloadListener {
- fun onDownloadStart(total: Long)
- fun onProgressChanged(progress: Long)
- fun onDownloadEnd(file: File)
- fun onFailed(t: Throwable)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt b/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
index 2334680..c658924 100644
--- a/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
@@ -14,10 +14,6 @@
const val PERMISSIONS_CODE = 999
const val MAX_DISTANCE = 5.5f //表盘最大显示距离
- const val FREE_INSPECTION = 20250101
- const val INSTALL_MARKER = 20250102
- const val DETECT_MARKER_DEPTH = 20250103
- const val SEARCH_MARKER = 20250104
const val AUTO_SAVE = "AUTO_SAVE"
const val USER_ACCOUNT = "USER_ACCOUNT"
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt b/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt
deleted file mode 100644
index 104f971..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.casic.common.detector.gd.utils
-
-object RuntimeCache {
- var currentSegment: CurrentSegment? = null
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt
index c5f18a6..b3dce3c 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt
@@ -1,26 +1,19 @@
package com.casic.common.detector.gd.view
import android.app.DatePickerDialog
-import android.content.ComponentName
-import android.content.Context
import android.content.DialogInterface
-import android.content.Intent
-import android.content.ServiceConnection
import android.hardware.Camera
import android.media.AudioAttributes
import android.media.SoundPool
import android.os.Bundle
import android.os.CountDownTimer
-import android.os.Handler
-import android.os.IBinder
-import android.os.Message
-import android.util.Log
import android.view.View
import android.widget.AdapterView
import androidx.lifecycle.ViewModelProvider
import com.amap.api.location.AMapLocation
import com.casic.common.detector.gd.R
import com.casic.common.detector.gd.adapter.EditableImageAdapter
+import com.casic.common.detector.gd.base.SerialPortActivity
import com.casic.common.detector.gd.bean.MarkerLocalBean
import com.casic.common.detector.gd.callback.OnGetLocationListener
import com.casic.common.detector.gd.callback.OnImageCompressListener
@@ -33,18 +26,15 @@
import com.casic.common.detector.gd.extensions.toColor
import com.casic.common.detector.gd.extensions.toMarkerId
import com.casic.common.detector.gd.extensions.toObjectType
-import com.casic.common.detector.gd.service.SerialPortService
import com.casic.common.detector.gd.utils.CurrentSegment
import com.casic.common.detector.gd.utils.DataBaseManager
import com.casic.common.detector.gd.utils.LocaleConstant
import com.casic.common.detector.gd.utils.LocationKit
-import com.casic.common.detector.gd.utils.RuntimeCache
import com.casic.common.detector.gd.vm.TaskViewModel
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.appendZero
import com.pengxh.kt.lite.extensions.dateToTimestamp
import com.pengxh.kt.lite.extensions.navigatePageTo
@@ -55,13 +45,12 @@
import com.pengxh.kt.lite.utils.LoadState
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.utils.SaveKeyValues
-import com.pengxh.kt.lite.utils.WeakReferenceHandler
import com.pengxh.kt.lite.widget.TitleBarView
import java.io.File
import java.util.Calendar
import java.util.Date
-class InstallMarkerActivity : KotlinBaseActivity(), Handler.Callback {
+class InstallMarkerActivity : SerialPortActivity() {
private val kTag = "InstallMarkerActivity"
private val context = this
@@ -73,7 +62,6 @@
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build()
private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build()
private var soundResourceId = 0
- private var serialPortService: SerialPortService? = null
private lateinit var imageAdapter: EditableImageAdapter
override fun initEvent() {
@@ -255,18 +243,18 @@
//读标识器
binding.readMarkerButton.setOnClickListener {
+ openSerialPort()
LoadingDialog.show(this, "标识器读取中,请稍后...")
countDownTimer.start()
binding.readMarkerButton.isEnabled = false
- RuntimeCache.currentSegment = CurrentSegment.InstallMarker
- serialPortService?.writeCommand('2')
+ readMarkerId()
}
}
- override fun handleMessage(msg: Message): Boolean {
- if (msg.what == LocaleConstant.INSTALL_MARKER) {
- val buffer = msg.obj as ByteArray
- if ((buffer.first().toInt() and 0xFF).toString(16).uppercase() == "30") {
+ override fun onDataReceived(buffer: ByteArray, segment: CurrentSegment) {
+ if (segment == CurrentSegment.InstallMarker) {
+ val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase()
+ if (flag == "30" && buffer.size == 10) {
val markerId = buffer.toMarkerId()
LoadingDialog.dismiss()
countDownTimer.cancel()
@@ -274,7 +262,6 @@
binding.identifierInclude.identifierIdView.text = markerId
}
}
- return true
}
/**
@@ -363,37 +350,7 @@
})
}
- private val serviceConnection = object : ServiceConnection {
- override fun onServiceConnected(name: ComponentName?, iBinder: IBinder?) {
- if (name != null && iBinder != null && iBinder is SerialPortService.ServiceBinder) {
- try {
- serialPortService = iBinder.getSerialPortService()
- Log.d(kTag, "onServiceConnected: 服务已绑定")
- } catch (e: Exception) {
- Log.e(kTag, "onServiceConnected: 绑定服务时发生异常", e)
- }
- } else {
- Log.w(kTag, "onServiceConnected: name 或 iBinder 为 null")
- }
- }
-
- override fun onServiceDisconnected(name: ComponentName?) {
- //在连接正常关闭的情况下不会被调用, 只在Service被破坏了或者被杀死的时候调用
- }
- }
-
- companion object {
- var weakReferenceHandler: WeakReferenceHandler? = null
- }
-
override fun initOnCreate(savedInstanceState: Bundle?) {
- weakReferenceHandler = WeakReferenceHandler(this)
-
- //绑定串口通信服务
- Intent(this, SerialPortService::class.java).also {
- bindService(it, serviceConnection, Context.BIND_AUTO_CREATE)
- }
-
locationKit.getCurrentLocation(true, object : OnGetLocationListener {
override fun onSuccess(location: AMapLocation) {
binding.identifierInclude.lngView.text = location.longitude.toString()
@@ -552,8 +509,6 @@
override fun onDestroy() {
super.onDestroy()
- RuntimeCache.currentSegment = null
locationKit.stopLocation()
- unbindService(serviceConnection)
}
}
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index c9b11ec..1a81160 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -77,7 +77,7 @@
dependencies {
//基础依赖库
- implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1'
+ implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.3'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
//Google官方授权框架
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2f152d8..5c645f0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -91,7 +91,6 @@
android:resource="@xml/file_paths" />
-
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
index 6cb496c..e5fe1f5 100644
--- a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
@@ -1,6 +1,7 @@
package com.casic.common.detector.gd.base
import android.app.Application
+import android.util.Log
import com.casic.common.detector.gd.greendao.DaoMaster
import com.casic.common.detector.gd.greendao.DaoSession
import com.casic.common.detector.gd.uart.SerialPort
@@ -52,6 +53,7 @@
//千寻报文数据下发串口号
add(SerialPort(File("/dev/ttyS1"), 9600, 0))
}
+ Log.d(kTag, "onCreate: 已初始化 ${serialPorts.size} 个串口")
} catch (e: SecurityException) {
"您没有串口的读写权限!".show(this)
} catch (e: IOException) {
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
new file mode 100644
index 0000000..08b3e19
--- /dev/null
+++ b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
@@ -0,0 +1,204 @@
+package com.casic.common.detector.gd.base
+
+import android.os.Bundle
+import android.os.Handler
+import android.os.Message
+import android.util.Log
+import androidx.appcompat.app.AppCompatActivity
+import androidx.viewbinding.ViewBinding
+import com.casic.common.detector.gd.utils.CurrentSegment
+import com.casic.common.detector.gd.utils.GpioManager
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import java.io.IOException
+import java.util.Timer
+import java.util.TimerTask
+import java.util.concurrent.atomic.AtomicInteger
+
+abstract class SerialPortActivity : AppCompatActivity(), Handler.Callback {
+
+ private val kTag = "SerialPortActivity"
+ private val taskTimer by lazy { Timer() }
+ private val weakReferenceHandler by lazy { WeakReferenceHandler(this) }
+
+ //输出流
+ private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
+
+ //输入流
+ private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
+ private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
+
+ private var segment: CurrentSegment? = null
+
+ protected lateinit var binding: VB
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = initViewBinding()
+ setContentView(binding.root)
+ setupTopBarLayout()
+ initOnCreate(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = firstInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = lastInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+ }
+
+ /**
+ * 初始化ViewBinding
+ */
+ abstract fun initViewBinding(): VB
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initOnCreate(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ abstract fun onDataReceived(buffer: ByteArray, segment: CurrentSegment)
+
+ override fun handleMessage(msg: Message): Boolean {
+ if (msg.what == 2025012001) {
+ val bytes = msg.obj as ByteArray
+ if (segment == null) {
+ return true
+ }
+ Log.d(kTag, "$segment - ${bytes.contentToString()}")
+ onDataReceived(bytes, segment!!)
+ }
+ return true
+ }
+
+ private var readMarkerIdTask: TimerTask? = null
+ private var searchMarkerTask: TimerTask? = null
+
+ fun readMarkerId() {
+ this.segment = CurrentSegment.InstallMarker
+ readMarkerIdTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(readMarkerIdTask, 0, 300)
+ }
+
+ fun detectDepth(tag: Char) {
+ this.segment = CurrentSegment.DetectDepth
+ outStream.write('3'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write(tag.code)
+ outStream.flush()
+ }
+
+ fun updateSegment(segment: CurrentSegment) {
+ this.segment = segment
+ }
+
+ fun searchMarker(segment: CurrentSegment) {
+ this.segment = segment
+ searchMarkerTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write('6'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(searchMarkerTask, 0, 300)
+ }
+
+ /***************************************************************************************/
+ private val gpioManager by lazy { GpioManager() }
+
+ /**
+ * 读取数据 1
+ * 暂停读取 0
+ * */
+ private val gpioState = AtomicInteger(0)
+ fun openSerialPort() {
+ if (gpioState.get() != 1) {
+ gpioManager.setGpioHigh("18")
+ gpioState.set(1)
+ Log.d(kTag, "openSerialPort: 调高串口电位")
+ } else {
+ Log.d(kTag, "openSerialPort: 已经是高电位,直接读数据")
+ }
+ }
+
+ fun closeSerialPort() {
+ if (segment != null) {
+ segment = null
+ }
+ readMarkerIdTask?.cancel()
+ searchMarkerTask?.cancel()
+ if (gpioState.get() == 0) {
+ Log.d(kTag, "closeSerialPort: 已经是低电位,不响应")
+ return
+ }
+ // 降低串口电位
+ gpioManager.setGpioLow("18")
+ gpioState.set(0)
+ Log.d(kTag, "closeSerialPort: 降低串口电位")
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ closeSerialPort()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
index 442189e..5c3ee01 100644
--- a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
@@ -1,42 +1,20 @@
package com.casic.common.detector.gd.extensions
-import android.util.Log
-
/**
* 因为数据频率很高,而且每一帧数据至少有一个信号值,如果有多个信号强度值,取平均值
*
* [78, 53, 49, 55, 51]
*
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
* */
fun ByteArray.toSignalStrength(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var strength = 0
+ for (byte in dataBytes) {
+ strength = strength * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return strength
}
/**
@@ -44,32 +22,13 @@
*
* [48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
*
- * [48, 48, 48, 56, 56, 57, 49, 48, 55, 51, 48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
- *
* */
fun ByteArray.toMarkerId(): String {
- //判断数据合理性
- val validBytes = if (this.size % 10 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 10) * 10
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ val id = this.map { it.toInt().toChar() }.joinToString("")
+ if (id.matches("-?\\d+".toRegex())) {
+ return id
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 10) {
- // 每10个字节取一次数据转为ASCII
- val tempBytes = validBytes.sliceArray(i until minOf(i + 10, validBytes.size))
- val string = tempBytes.map { it.toInt().toChar() }.joinToString("")
- if (string.matches("-?\\d+".toRegex())) {
- list.add(string)
- } else {
- Log.d("kTag", "toDeviceCode: 编号解析失败")
- }
- }
- return list.last()
+ return ""
}
/**
@@ -77,31 +36,14 @@
*
* [83, 48, 48, 48, 57]
*
- * [83, 48, 48, 48, 57, 83, 48, 48, 48, 57]
* */
fun ByteArray.toBuryDepth(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var depth = 0
+ for (byte in dataBytes) {
+ depth = depth * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return depth
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt b/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
deleted file mode 100644
index 76cf583..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
+++ /dev/null
@@ -1,136 +0,0 @@
-package com.casic.common.detector.gd.service
-
-import android.app.Service
-import android.content.Intent
-import android.os.Binder
-import android.os.IBinder
-import android.util.Log
-import com.casic.common.detector.gd.base.BaseApplication
-import com.casic.common.detector.gd.utils.CurrentSegment
-import com.casic.common.detector.gd.utils.LocaleConstant
-import com.casic.common.detector.gd.utils.RuntimeCache
-import com.casic.common.detector.gd.view.InstallMarkerActivity
-import com.casic.common.detector.gd.view.MainActivity
-import com.casic.common.detector.gd.view.SearchMarkerActivity
-import java.io.IOException
-import java.io.InputStream
-import java.util.concurrent.Executors
-import java.util.concurrent.TimeUnit
-
-class SerialPortService : Service() {
-
- private val kTag = "SerialPortService"
- private val sendExecutor = Executors.newFixedThreadPool(5)
- private val readExecutor = Executors.newSingleThreadScheduledExecutor()
-
- //输出流
- private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
-
- //输入流
- private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
- private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
-
- override fun onCreate() {
- super.onCreate()
- try {
- // 使用单线程调度器读取数据
- readExecutor.scheduleAtFixedRate({
- readData(firstInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
-
- readExecutor.scheduleAtFixedRate({
- readData(lastInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- private fun readData(inputStream: InputStream) {
- try {
- val buffer = ByteArray(1024)
- var bytesRead: Int
- while (inputStream.available() > 0) {
- bytesRead = inputStream.read(buffer)
- if (bytesRead > 0) {
- when (RuntimeCache.currentSegment) {
- CurrentSegment.DetectMarkerDepth -> {
- //深度
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.DETECT_MARKER_DEPTH
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.InstallMarker -> {
- //安装点
- InstallMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.INSTALL_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.FreeInspection -> {
- //自由巡检
- MainActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.FREE_INSPECTION
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.SearchMarker -> {
- //搜索标识器
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.SEARCH_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- else -> {
- val bytes = buffer.copyOf(bytesRead)
- Log.d(kTag, "空状态,不处理 ===> ${bytes.contentToString()}")
- }
- }
- }
- }
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- fun writeCommand(vararg command: Char) {
- Log.d(kTag, "writeCommand: ${command.contentToString()}")
- if (command.size == 1) {
- sendExecutor.submit {
- outStream.write(command.first().code)
- outStream.flush()
- }
- } else {
- command.forEach {
- sendExecutor.submit {
- outStream.write(it.code)
- outStream.flush()
- }
- Thread.sleep(1000)
- }
- }
- }
-
- override fun onBind(intent: Intent?): IBinder {
- return ServiceBinder()
- }
-
- inner class ServiceBinder : Binder() {
- fun getSerialPortService(): SerialPortService {
- return this@SerialPortService
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt b/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
index 0606b72..9efa097 100644
--- a/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
@@ -1,23 +1,23 @@
package com.casic.common.detector.gd.utils
-sealed class CurrentSegment {
+enum class CurrentSegment {
/**
* 安装标识器
* */
- object InstallMarker : CurrentSegment()
+ InstallMarker,
/**
* 自由巡检
* */
- object FreeInspection : CurrentSegment()
+ FreeInspection,
/**
* 搜索标识器
* */
- object SearchMarker : CurrentSegment()
+ SearchMarker,
/**
* 探测标识器深度
* */
- object DetectMarkerDepth : CurrentSegment()
+ DetectDepth
}
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt
deleted file mode 100644
index c9151a8..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt
+++ /dev/null
@@ -1,150 +0,0 @@
-package com.casic.common.detector.gd.utils
-
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.SupervisorJob
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import okhttp3.Call
-import okhttp3.Callback
-import okhttp3.OkHttpClient
-import okhttp3.Request
-import okhttp3.Response
-import java.io.File
-import java.io.IOException
-import java.util.concurrent.atomic.AtomicBoolean
-
-class FileDownloadManager(builder: Builder) {
-
- private val httpClient by lazy { OkHttpClient() }
-
- class Builder {
- lateinit var url: String
- lateinit var suffix: String
- lateinit var directory: File
- lateinit var downloadListener: OnFileDownloadListener
-
- /**
- * 文件下载地址
- * */
- fun setDownloadFileSource(url: String): Builder {
- this.url = url
- return this
- }
-
- /**
- * 文件后缀
- * 如:apk等
- * */
- fun setFileSuffix(suffix: String): Builder {
- this.suffix = if (suffix.contains(".")) {
- //去掉前缀的点
- suffix.drop(1)
- } else {
- suffix
- }
- return this
- }
-
- /**
- * 文件保存的地址
- * */
- fun setFileSaveDirectory(directory: File): Builder {
- this.directory = directory
- return this
- }
-
- /**
- * 设置文件下载回调监听
- * */
- fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder {
- this.downloadListener = downloadListener
- return this
- }
-
- fun build(): FileDownloadManager {
- if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) {
- throw IllegalStateException("All properties must be initialized before building.")
- }
- return FileDownloadManager(this)
- }
- }
-
- private val url = builder.url
- private val suffix = builder.suffix
- private val directory = builder.directory
- private val listener = builder.downloadListener
-
- /**
- * 开始下载
- * */
- fun start() {
- val job = SupervisorJob()
- val scope = CoroutineScope(Dispatchers.Main + job)
-
- val request = Request.Builder().get().url(url).build()
- val newCall = httpClient.newCall(request)
- val isExecuting = AtomicBoolean(false)
-
- /**
- * 如果已被加入下载队列,则取消之前的,重新下载
- */
- if (isExecuting.getAndSet(true)) {
- newCall.cancel()
- }
-
- //异步下载文件
- newCall.enqueue(object : Callback {
- override fun onFailure(call: Call, e: IOException) {
- scope.launch(Dispatchers.Main) {
- listener.onFailed(e)
- }
- }
-
- override fun onResponse(call: Call, response: Response) {
- scope.launch(Dispatchers.IO) {
- val body = response.body
- if (body == null) {
- listener.onFailed(IOException("Response body is null"))
- throw IOException("Response body is null")
- } else {
- val inputStream = body.byteStream()
- val fileSize = body.contentLength()
-
- if (fileSize <= 0) {
- throw IllegalArgumentException("Invalid file size")
- }
- listener.onDownloadStart(fileSize)
-
- val file = File(directory, "${System.currentTimeMillis()}.${suffix}")
- file.outputStream().use { fos ->
- val buffer = ByteArray(2048)
- var sum = 0L
- var read: Int
- while (inputStream.read(buffer).also { read = it } != -1) {
- fos.write(buffer, 0, read)
- sum += read.toLong()
- withContext(Dispatchers.Main) {
- listener.onProgressChanged(sum)
- }
- }
- }
-
- withContext(Dispatchers.Main) {
- listener.onDownloadEnd(file)
- }
-
- job.cancel()
- }
- }
- }
- })
- }
-
- interface OnFileDownloadListener {
- fun onDownloadStart(total: Long)
- fun onProgressChanged(progress: Long)
- fun onDownloadEnd(file: File)
- fun onFailed(t: Throwable)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt b/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
index 2334680..c658924 100644
--- a/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
@@ -14,10 +14,6 @@
const val PERMISSIONS_CODE = 999
const val MAX_DISTANCE = 5.5f //表盘最大显示距离
- const val FREE_INSPECTION = 20250101
- const val INSTALL_MARKER = 20250102
- const val DETECT_MARKER_DEPTH = 20250103
- const val SEARCH_MARKER = 20250104
const val AUTO_SAVE = "AUTO_SAVE"
const val USER_ACCOUNT = "USER_ACCOUNT"
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt b/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt
deleted file mode 100644
index 104f971..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.casic.common.detector.gd.utils
-
-object RuntimeCache {
- var currentSegment: CurrentSegment? = null
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt
index c5f18a6..b3dce3c 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt
@@ -1,26 +1,19 @@
package com.casic.common.detector.gd.view
import android.app.DatePickerDialog
-import android.content.ComponentName
-import android.content.Context
import android.content.DialogInterface
-import android.content.Intent
-import android.content.ServiceConnection
import android.hardware.Camera
import android.media.AudioAttributes
import android.media.SoundPool
import android.os.Bundle
import android.os.CountDownTimer
-import android.os.Handler
-import android.os.IBinder
-import android.os.Message
-import android.util.Log
import android.view.View
import android.widget.AdapterView
import androidx.lifecycle.ViewModelProvider
import com.amap.api.location.AMapLocation
import com.casic.common.detector.gd.R
import com.casic.common.detector.gd.adapter.EditableImageAdapter
+import com.casic.common.detector.gd.base.SerialPortActivity
import com.casic.common.detector.gd.bean.MarkerLocalBean
import com.casic.common.detector.gd.callback.OnGetLocationListener
import com.casic.common.detector.gd.callback.OnImageCompressListener
@@ -33,18 +26,15 @@
import com.casic.common.detector.gd.extensions.toColor
import com.casic.common.detector.gd.extensions.toMarkerId
import com.casic.common.detector.gd.extensions.toObjectType
-import com.casic.common.detector.gd.service.SerialPortService
import com.casic.common.detector.gd.utils.CurrentSegment
import com.casic.common.detector.gd.utils.DataBaseManager
import com.casic.common.detector.gd.utils.LocaleConstant
import com.casic.common.detector.gd.utils.LocationKit
-import com.casic.common.detector.gd.utils.RuntimeCache
import com.casic.common.detector.gd.vm.TaskViewModel
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.appendZero
import com.pengxh.kt.lite.extensions.dateToTimestamp
import com.pengxh.kt.lite.extensions.navigatePageTo
@@ -55,13 +45,12 @@
import com.pengxh.kt.lite.utils.LoadState
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.utils.SaveKeyValues
-import com.pengxh.kt.lite.utils.WeakReferenceHandler
import com.pengxh.kt.lite.widget.TitleBarView
import java.io.File
import java.util.Calendar
import java.util.Date
-class InstallMarkerActivity : KotlinBaseActivity(), Handler.Callback {
+class InstallMarkerActivity : SerialPortActivity() {
private val kTag = "InstallMarkerActivity"
private val context = this
@@ -73,7 +62,6 @@
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build()
private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build()
private var soundResourceId = 0
- private var serialPortService: SerialPortService? = null
private lateinit var imageAdapter: EditableImageAdapter
override fun initEvent() {
@@ -255,18 +243,18 @@
//读标识器
binding.readMarkerButton.setOnClickListener {
+ openSerialPort()
LoadingDialog.show(this, "标识器读取中,请稍后...")
countDownTimer.start()
binding.readMarkerButton.isEnabled = false
- RuntimeCache.currentSegment = CurrentSegment.InstallMarker
- serialPortService?.writeCommand('2')
+ readMarkerId()
}
}
- override fun handleMessage(msg: Message): Boolean {
- if (msg.what == LocaleConstant.INSTALL_MARKER) {
- val buffer = msg.obj as ByteArray
- if ((buffer.first().toInt() and 0xFF).toString(16).uppercase() == "30") {
+ override fun onDataReceived(buffer: ByteArray, segment: CurrentSegment) {
+ if (segment == CurrentSegment.InstallMarker) {
+ val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase()
+ if (flag == "30" && buffer.size == 10) {
val markerId = buffer.toMarkerId()
LoadingDialog.dismiss()
countDownTimer.cancel()
@@ -274,7 +262,6 @@
binding.identifierInclude.identifierIdView.text = markerId
}
}
- return true
}
/**
@@ -363,37 +350,7 @@
})
}
- private val serviceConnection = object : ServiceConnection {
- override fun onServiceConnected(name: ComponentName?, iBinder: IBinder?) {
- if (name != null && iBinder != null && iBinder is SerialPortService.ServiceBinder) {
- try {
- serialPortService = iBinder.getSerialPortService()
- Log.d(kTag, "onServiceConnected: 服务已绑定")
- } catch (e: Exception) {
- Log.e(kTag, "onServiceConnected: 绑定服务时发生异常", e)
- }
- } else {
- Log.w(kTag, "onServiceConnected: name 或 iBinder 为 null")
- }
- }
-
- override fun onServiceDisconnected(name: ComponentName?) {
- //在连接正常关闭的情况下不会被调用, 只在Service被破坏了或者被杀死的时候调用
- }
- }
-
- companion object {
- var weakReferenceHandler: WeakReferenceHandler? = null
- }
-
override fun initOnCreate(savedInstanceState: Bundle?) {
- weakReferenceHandler = WeakReferenceHandler(this)
-
- //绑定串口通信服务
- Intent(this, SerialPortService::class.java).also {
- bindService(it, serviceConnection, Context.BIND_AUTO_CREATE)
- }
-
locationKit.getCurrentLocation(true, object : OnGetLocationListener {
override fun onSuccess(location: AMapLocation) {
binding.identifierInclude.lngView.text = location.longitude.toString()
@@ -552,8 +509,6 @@
override fun onDestroy() {
super.onDestroy()
- RuntimeCache.currentSegment = null
locationKit.stopLocation()
- unbindService(serviceConnection)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt
index 8a798b6..2c48cc9 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt
@@ -1,18 +1,12 @@
package com.casic.common.detector.gd.view
import android.app.Activity
-import android.content.ComponentName
-import android.content.Context
import android.content.Intent
-import android.content.ServiceConnection
import android.graphics.BitmapFactory
import android.graphics.Color
import android.media.AudioAttributes
import android.media.SoundPool
import android.os.Bundle
-import android.os.Handler
-import android.os.IBinder
-import android.os.Message
import android.util.Log
import android.view.KeyEvent
import android.view.View
@@ -34,6 +28,7 @@
import com.amap.api.maps.model.MyLocationStyle
import com.casic.common.detector.gd.R
import com.casic.common.detector.gd.base.BaseApplication
+import com.casic.common.detector.gd.base.SerialPortActivity
import com.casic.common.detector.gd.bean.MarkerLocalBean
import com.casic.common.detector.gd.bean.TaskLocalBean
import com.casic.common.detector.gd.callback.OnGetAddressListener
@@ -47,32 +42,27 @@
import com.casic.common.detector.gd.model.TaskDetailLocalModel
import com.casic.common.detector.gd.model.TaskModel
import com.casic.common.detector.gd.service.NtripConnectService
-import com.casic.common.detector.gd.service.SerialPortService
import com.casic.common.detector.gd.utils.CurrentSegment
import com.casic.common.detector.gd.utils.DataBaseManager
import com.casic.common.detector.gd.utils.ExcelKit
-import com.casic.common.detector.gd.utils.FileDownloadManager
import com.casic.common.detector.gd.utils.FileType
-import com.casic.common.detector.gd.utils.GpioManager
import com.casic.common.detector.gd.utils.LocaleConstant
import com.casic.common.detector.gd.utils.LocationKit
import com.casic.common.detector.gd.utils.RouteOnMap
-import com.casic.common.detector.gd.utils.RuntimeCache
import com.casic.common.detector.gd.vm.TaskViewModel
import com.casic.common.detector.gd.widgets.MarkerDetailDialog
import com.casic.common.detector.gd.widgets.QueryMarkerDialog
import com.casic.common.detector.gd.widgets.SamplePopupWindow
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.createDownloadFileDir
import com.pengxh.kt.lite.extensions.dp2px
import com.pengxh.kt.lite.extensions.isNetworkConnected
import com.pengxh.kt.lite.extensions.navigatePageTo
import com.pengxh.kt.lite.extensions.show
import com.pengxh.kt.lite.extensions.timestampToCompleteDate
+import com.pengxh.kt.lite.utils.FileDownloadManager
import com.pengxh.kt.lite.utils.LoadState
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.utils.SaveKeyValues
-import com.pengxh.kt.lite.utils.WeakReferenceHandler
import com.pengxh.kt.lite.widget.TitleBarView
import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
import com.pengxh.kt.lite.widget.dialog.AlertInputDialog
@@ -82,45 +72,13 @@
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
-import java.util.concurrent.atomic.AtomicInteger
-class MainActivity : KotlinBaseActivity(), AMap.OnMarkerClickListener,
- OnMapLongClickListener, Handler.Callback {
+class MainActivity : SerialPortActivity(), AMap.OnMarkerClickListener,
+ OnMapLongClickListener {
private val kTag = "MainActivity"
private val context = this
-
- /***************************************************************************************/
- private val gpioManager by lazy { GpioManager() }
-
- /**
- * 读取数据 1
- * 暂停读取 0
- * */
- private val gpioState = AtomicInteger(0)
- private fun openSerialPort() {
- if (gpioState.get() != 1) {
- gpioManager.setGpioHigh("18")
- gpioState.set(1)
- Log.d(kTag, "openSerialPort: 调高串口电位")
- } else {
- Log.d(kTag, "openSerialPort: 已经是高电位,直接读数据")
- }
- }
-
- private fun closeSerialPort() {
- if (gpioState.get() == 0) {
- Log.d(kTag, "closeSerialPort: 已经是低电位,直接返回")
- return
- }
- // 降低串口电位
- gpioManager.setGpioLow("18")
- gpioState.set(0)
- Log.d(kTag, "closeSerialPort: 降低串口电位")
- }
-
- /***************************************************************************************/
private val samplePopupWindow by lazy { SamplePopupWindow(this) }
private val detailDialog by lazy { MarkerDetailDialog(this) }
private val locationKit by lazy { LocationKit(this) }
@@ -133,7 +91,6 @@
private var freeTaskTitle = ""
private var ids = HashSet()
private var freeTaskId: String? = null
- private var serialPortService: SerialPortService? = null
private var soundResourceId = 0
private var isExecuteTask = false
private lateinit var aMap: AMap
@@ -146,43 +103,13 @@
binding.rootView.initImmersionBar(this, false, R.color.themeColor)
}
- private val serviceConnection = object : ServiceConnection {
- override fun onServiceConnected(name: ComponentName?, iBinder: IBinder?) {
- if (name != null && iBinder != null && iBinder is SerialPortService.ServiceBinder) {
- try {
- serialPortService = iBinder.getSerialPortService()
- Log.d(kTag, "onServiceConnected: 服务已绑定")
- openSerialPort()
- } catch (e: Exception) {
- Log.e(kTag, "onServiceConnected: 绑定服务时发生异常", e)
- }
- } else {
- Log.w(kTag, "onServiceConnected: name 或 iBinder 为 null")
- }
- }
-
- override fun onServiceDisconnected(name: ComponentName?) {
-
- }
- }
-
- companion object {
- var weakReferenceHandler: WeakReferenceHandler? = null
- }
-
override fun initOnCreate(savedInstanceState: Bundle?) {
- weakReferenceHandler = WeakReferenceHandler(this)
-
//地图初始化
initMapConfig(savedInstanceState)
- //绑定串口通信服务
- Intent(this, SerialPortService::class.java).also {
- bindService(it, serviceConnection, Context.BIND_AUTO_CREATE)
- }
- Intent(this, NtripConnectService::class.java).also {
- startService(it)
- }
+// Intent(this, NtripConnectService::class.java).also {
+// startService(it)
+// }
soundResourceId = soundPool.load(this, R.raw.ring3, 1)
//右上角菜单
@@ -211,7 +138,7 @@
showMarkersOnMap()
}
- override fun onFailed(t: Throwable) {
+ override fun onDownloadFailed(t: Throwable) {
t.printStackTrace()
}
@@ -446,7 +373,7 @@
override fun onConfirmClick() {
isFreeTask = false
soundPool.autoPause()
- RuntimeCache.currentSegment = null
+ closeSerialPort()
binding.stopFreeTaskButton.visibility = View.GONE
if (freeTaskId.isNullOrBlank()) {
@@ -499,11 +426,7 @@
} else {
"此工单下无标识器,将执行自由巡检任务".show(context)
freeTaskId = task.taskId
-
- binding.stopFreeTaskButton.visibility = View.VISIBLE
- isFreeTask = true
- RuntimeCache.currentSegment = CurrentSegment.FreeInspection
- serialPortService?.writeCommand('2', '6')
+ detectMarker()
}
}
@@ -524,21 +447,22 @@
freeTaskTitle = value
val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String
taskViewModel.createFreeTask(context, userId, value)
-
- binding.stopFreeTaskButton.visibility = View.VISIBLE
- isFreeTask = true
- RuntimeCache.currentSegment = CurrentSegment.FreeInspection
- serialPortService?.writeCommand('2', '6')
+ detectMarker()
}
override fun onCancelClick() {}
}).build().show()
}
- override fun handleMessage(msg: Message): Boolean {
- if (msg.what == LocaleConstant.FREE_INSPECTION) {
- val buffer = msg.obj as ByteArray
- //只响一次,因为探测频率高,所以依旧是连续的报警声
+ private fun detectMarker() {
+ binding.stopFreeTaskButton.visibility = View.VISIBLE
+ isFreeTask = true
+ openSerialPort()
+ searchMarker(CurrentSegment.FreeInspection)
+ }
+
+ override fun onDataReceived(buffer: ByteArray, segment: CurrentSegment) {
+ if (segment == CurrentSegment.FreeInspection) {
soundPool.play(soundResourceId, 1f, 1f, 0, 0, 1f)
when ((buffer.first().toInt() and 0xFF).toString(16).uppercase()) {
"4E" -> {
@@ -552,27 +476,30 @@
val markerId = buffer.toMarkerId()
//添加地图Marker
if (!ids.contains(markerId)) {
- //根据markerId查询标识器经纬度
- val labels = DataBaseManager.get.queryMarkerById(markerId)
- if (labels.isNotEmpty()) {
- val bean = labels.first()
- aMap.addMarker(
- MarkerOptions()
- .position(LatLng(bean.lat.toDouble(), bean.lng.toDouble()))
- .icon(BitmapDescriptorFactory.fromResource(R.mipmap.label_blue1))
+ val markers = DataBaseManager.get.queryMarkerById(markerId)
+ if (markers.isNotEmpty()) {
+ val marker = markers.first()
+ val latLng = LatLng(
+ marker.lat.toDouble(), marker.lng.toDouble()
)
+ val resource = BitmapDescriptorFactory.fromResource(
+ R.mipmap.label_blue1
+ )
+ val options = MarkerOptions().position(latLng).icon(resource)
+ aMap.addMarker(options)
}
}
ids.add(markerId)
//显示标识器详细信息
if (!detailDialog.isShowing) {
- val markerBean = DataBaseManager.get.queryMarkerById(markerId).firstOrNull()
- if (markerBean == null) {
- "无法查询到此ID【${markerId}】的信息".show(context)
- } else {
- detailDialog.setMarker(markerBean)
- detailDialog.show()
+ DataBaseManager.get.queryMarkerById(markerId).firstOrNull().apply {
+ if (this == null) {
+ "无法查询到此ID【${markerId}】的信息".show(context)
+ } else {
+ detailDialog.setMarker(this)
+ detailDialog.show()
+ }
}
}
}
@@ -582,7 +509,6 @@
}
}
}
- return true
}
override fun observeRequestState() {
@@ -865,9 +791,6 @@
override fun onResume() {
super.onResume()
binding.mapView.onResume()
- if (serialPortService != null) {
- openSerialPort()
- }
}
override fun onPause() {
@@ -885,8 +808,6 @@
binding.mapView.onDestroy()
soundPool.autoPause()
locationKit.stopLocation()
- unbindService(serviceConnection)
- closeSerialPort()
BaseApplication.get().closeSerialPort()
}
}
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index c9b11ec..1a81160 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -77,7 +77,7 @@
dependencies {
//基础依赖库
- implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1'
+ implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.3'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
//Google官方授权框架
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2f152d8..5c645f0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -91,7 +91,6 @@
android:resource="@xml/file_paths" />
-
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
index 6cb496c..e5fe1f5 100644
--- a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
@@ -1,6 +1,7 @@
package com.casic.common.detector.gd.base
import android.app.Application
+import android.util.Log
import com.casic.common.detector.gd.greendao.DaoMaster
import com.casic.common.detector.gd.greendao.DaoSession
import com.casic.common.detector.gd.uart.SerialPort
@@ -52,6 +53,7 @@
//千寻报文数据下发串口号
add(SerialPort(File("/dev/ttyS1"), 9600, 0))
}
+ Log.d(kTag, "onCreate: 已初始化 ${serialPorts.size} 个串口")
} catch (e: SecurityException) {
"您没有串口的读写权限!".show(this)
} catch (e: IOException) {
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
new file mode 100644
index 0000000..08b3e19
--- /dev/null
+++ b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
@@ -0,0 +1,204 @@
+package com.casic.common.detector.gd.base
+
+import android.os.Bundle
+import android.os.Handler
+import android.os.Message
+import android.util.Log
+import androidx.appcompat.app.AppCompatActivity
+import androidx.viewbinding.ViewBinding
+import com.casic.common.detector.gd.utils.CurrentSegment
+import com.casic.common.detector.gd.utils.GpioManager
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import java.io.IOException
+import java.util.Timer
+import java.util.TimerTask
+import java.util.concurrent.atomic.AtomicInteger
+
+abstract class SerialPortActivity : AppCompatActivity(), Handler.Callback {
+
+ private val kTag = "SerialPortActivity"
+ private val taskTimer by lazy { Timer() }
+ private val weakReferenceHandler by lazy { WeakReferenceHandler(this) }
+
+ //输出流
+ private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
+
+ //输入流
+ private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
+ private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
+
+ private var segment: CurrentSegment? = null
+
+ protected lateinit var binding: VB
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = initViewBinding()
+ setContentView(binding.root)
+ setupTopBarLayout()
+ initOnCreate(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = firstInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = lastInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+ }
+
+ /**
+ * 初始化ViewBinding
+ */
+ abstract fun initViewBinding(): VB
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initOnCreate(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ abstract fun onDataReceived(buffer: ByteArray, segment: CurrentSegment)
+
+ override fun handleMessage(msg: Message): Boolean {
+ if (msg.what == 2025012001) {
+ val bytes = msg.obj as ByteArray
+ if (segment == null) {
+ return true
+ }
+ Log.d(kTag, "$segment - ${bytes.contentToString()}")
+ onDataReceived(bytes, segment!!)
+ }
+ return true
+ }
+
+ private var readMarkerIdTask: TimerTask? = null
+ private var searchMarkerTask: TimerTask? = null
+
+ fun readMarkerId() {
+ this.segment = CurrentSegment.InstallMarker
+ readMarkerIdTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(readMarkerIdTask, 0, 300)
+ }
+
+ fun detectDepth(tag: Char) {
+ this.segment = CurrentSegment.DetectDepth
+ outStream.write('3'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write(tag.code)
+ outStream.flush()
+ }
+
+ fun updateSegment(segment: CurrentSegment) {
+ this.segment = segment
+ }
+
+ fun searchMarker(segment: CurrentSegment) {
+ this.segment = segment
+ searchMarkerTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write('6'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(searchMarkerTask, 0, 300)
+ }
+
+ /***************************************************************************************/
+ private val gpioManager by lazy { GpioManager() }
+
+ /**
+ * 读取数据 1
+ * 暂停读取 0
+ * */
+ private val gpioState = AtomicInteger(0)
+ fun openSerialPort() {
+ if (gpioState.get() != 1) {
+ gpioManager.setGpioHigh("18")
+ gpioState.set(1)
+ Log.d(kTag, "openSerialPort: 调高串口电位")
+ } else {
+ Log.d(kTag, "openSerialPort: 已经是高电位,直接读数据")
+ }
+ }
+
+ fun closeSerialPort() {
+ if (segment != null) {
+ segment = null
+ }
+ readMarkerIdTask?.cancel()
+ searchMarkerTask?.cancel()
+ if (gpioState.get() == 0) {
+ Log.d(kTag, "closeSerialPort: 已经是低电位,不响应")
+ return
+ }
+ // 降低串口电位
+ gpioManager.setGpioLow("18")
+ gpioState.set(0)
+ Log.d(kTag, "closeSerialPort: 降低串口电位")
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ closeSerialPort()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
index 442189e..5c3ee01 100644
--- a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
@@ -1,42 +1,20 @@
package com.casic.common.detector.gd.extensions
-import android.util.Log
-
/**
* 因为数据频率很高,而且每一帧数据至少有一个信号值,如果有多个信号强度值,取平均值
*
* [78, 53, 49, 55, 51]
*
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
* */
fun ByteArray.toSignalStrength(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var strength = 0
+ for (byte in dataBytes) {
+ strength = strength * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return strength
}
/**
@@ -44,32 +22,13 @@
*
* [48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
*
- * [48, 48, 48, 56, 56, 57, 49, 48, 55, 51, 48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
- *
* */
fun ByteArray.toMarkerId(): String {
- //判断数据合理性
- val validBytes = if (this.size % 10 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 10) * 10
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ val id = this.map { it.toInt().toChar() }.joinToString("")
+ if (id.matches("-?\\d+".toRegex())) {
+ return id
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 10) {
- // 每10个字节取一次数据转为ASCII
- val tempBytes = validBytes.sliceArray(i until minOf(i + 10, validBytes.size))
- val string = tempBytes.map { it.toInt().toChar() }.joinToString("")
- if (string.matches("-?\\d+".toRegex())) {
- list.add(string)
- } else {
- Log.d("kTag", "toDeviceCode: 编号解析失败")
- }
- }
- return list.last()
+ return ""
}
/**
@@ -77,31 +36,14 @@
*
* [83, 48, 48, 48, 57]
*
- * [83, 48, 48, 48, 57, 83, 48, 48, 48, 57]
* */
fun ByteArray.toBuryDepth(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var depth = 0
+ for (byte in dataBytes) {
+ depth = depth * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return depth
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt b/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
deleted file mode 100644
index 76cf583..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
+++ /dev/null
@@ -1,136 +0,0 @@
-package com.casic.common.detector.gd.service
-
-import android.app.Service
-import android.content.Intent
-import android.os.Binder
-import android.os.IBinder
-import android.util.Log
-import com.casic.common.detector.gd.base.BaseApplication
-import com.casic.common.detector.gd.utils.CurrentSegment
-import com.casic.common.detector.gd.utils.LocaleConstant
-import com.casic.common.detector.gd.utils.RuntimeCache
-import com.casic.common.detector.gd.view.InstallMarkerActivity
-import com.casic.common.detector.gd.view.MainActivity
-import com.casic.common.detector.gd.view.SearchMarkerActivity
-import java.io.IOException
-import java.io.InputStream
-import java.util.concurrent.Executors
-import java.util.concurrent.TimeUnit
-
-class SerialPortService : Service() {
-
- private val kTag = "SerialPortService"
- private val sendExecutor = Executors.newFixedThreadPool(5)
- private val readExecutor = Executors.newSingleThreadScheduledExecutor()
-
- //输出流
- private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
-
- //输入流
- private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
- private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
-
- override fun onCreate() {
- super.onCreate()
- try {
- // 使用单线程调度器读取数据
- readExecutor.scheduleAtFixedRate({
- readData(firstInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
-
- readExecutor.scheduleAtFixedRate({
- readData(lastInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- private fun readData(inputStream: InputStream) {
- try {
- val buffer = ByteArray(1024)
- var bytesRead: Int
- while (inputStream.available() > 0) {
- bytesRead = inputStream.read(buffer)
- if (bytesRead > 0) {
- when (RuntimeCache.currentSegment) {
- CurrentSegment.DetectMarkerDepth -> {
- //深度
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.DETECT_MARKER_DEPTH
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.InstallMarker -> {
- //安装点
- InstallMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.INSTALL_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.FreeInspection -> {
- //自由巡检
- MainActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.FREE_INSPECTION
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.SearchMarker -> {
- //搜索标识器
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.SEARCH_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- else -> {
- val bytes = buffer.copyOf(bytesRead)
- Log.d(kTag, "空状态,不处理 ===> ${bytes.contentToString()}")
- }
- }
- }
- }
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- fun writeCommand(vararg command: Char) {
- Log.d(kTag, "writeCommand: ${command.contentToString()}")
- if (command.size == 1) {
- sendExecutor.submit {
- outStream.write(command.first().code)
- outStream.flush()
- }
- } else {
- command.forEach {
- sendExecutor.submit {
- outStream.write(it.code)
- outStream.flush()
- }
- Thread.sleep(1000)
- }
- }
- }
-
- override fun onBind(intent: Intent?): IBinder {
- return ServiceBinder()
- }
-
- inner class ServiceBinder : Binder() {
- fun getSerialPortService(): SerialPortService {
- return this@SerialPortService
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt b/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
index 0606b72..9efa097 100644
--- a/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
@@ -1,23 +1,23 @@
package com.casic.common.detector.gd.utils
-sealed class CurrentSegment {
+enum class CurrentSegment {
/**
* 安装标识器
* */
- object InstallMarker : CurrentSegment()
+ InstallMarker,
/**
* 自由巡检
* */
- object FreeInspection : CurrentSegment()
+ FreeInspection,
/**
* 搜索标识器
* */
- object SearchMarker : CurrentSegment()
+ SearchMarker,
/**
* 探测标识器深度
* */
- object DetectMarkerDepth : CurrentSegment()
+ DetectDepth
}
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt
deleted file mode 100644
index c9151a8..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt
+++ /dev/null
@@ -1,150 +0,0 @@
-package com.casic.common.detector.gd.utils
-
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.SupervisorJob
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import okhttp3.Call
-import okhttp3.Callback
-import okhttp3.OkHttpClient
-import okhttp3.Request
-import okhttp3.Response
-import java.io.File
-import java.io.IOException
-import java.util.concurrent.atomic.AtomicBoolean
-
-class FileDownloadManager(builder: Builder) {
-
- private val httpClient by lazy { OkHttpClient() }
-
- class Builder {
- lateinit var url: String
- lateinit var suffix: String
- lateinit var directory: File
- lateinit var downloadListener: OnFileDownloadListener
-
- /**
- * 文件下载地址
- * */
- fun setDownloadFileSource(url: String): Builder {
- this.url = url
- return this
- }
-
- /**
- * 文件后缀
- * 如:apk等
- * */
- fun setFileSuffix(suffix: String): Builder {
- this.suffix = if (suffix.contains(".")) {
- //去掉前缀的点
- suffix.drop(1)
- } else {
- suffix
- }
- return this
- }
-
- /**
- * 文件保存的地址
- * */
- fun setFileSaveDirectory(directory: File): Builder {
- this.directory = directory
- return this
- }
-
- /**
- * 设置文件下载回调监听
- * */
- fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder {
- this.downloadListener = downloadListener
- return this
- }
-
- fun build(): FileDownloadManager {
- if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) {
- throw IllegalStateException("All properties must be initialized before building.")
- }
- return FileDownloadManager(this)
- }
- }
-
- private val url = builder.url
- private val suffix = builder.suffix
- private val directory = builder.directory
- private val listener = builder.downloadListener
-
- /**
- * 开始下载
- * */
- fun start() {
- val job = SupervisorJob()
- val scope = CoroutineScope(Dispatchers.Main + job)
-
- val request = Request.Builder().get().url(url).build()
- val newCall = httpClient.newCall(request)
- val isExecuting = AtomicBoolean(false)
-
- /**
- * 如果已被加入下载队列,则取消之前的,重新下载
- */
- if (isExecuting.getAndSet(true)) {
- newCall.cancel()
- }
-
- //异步下载文件
- newCall.enqueue(object : Callback {
- override fun onFailure(call: Call, e: IOException) {
- scope.launch(Dispatchers.Main) {
- listener.onFailed(e)
- }
- }
-
- override fun onResponse(call: Call, response: Response) {
- scope.launch(Dispatchers.IO) {
- val body = response.body
- if (body == null) {
- listener.onFailed(IOException("Response body is null"))
- throw IOException("Response body is null")
- } else {
- val inputStream = body.byteStream()
- val fileSize = body.contentLength()
-
- if (fileSize <= 0) {
- throw IllegalArgumentException("Invalid file size")
- }
- listener.onDownloadStart(fileSize)
-
- val file = File(directory, "${System.currentTimeMillis()}.${suffix}")
- file.outputStream().use { fos ->
- val buffer = ByteArray(2048)
- var sum = 0L
- var read: Int
- while (inputStream.read(buffer).also { read = it } != -1) {
- fos.write(buffer, 0, read)
- sum += read.toLong()
- withContext(Dispatchers.Main) {
- listener.onProgressChanged(sum)
- }
- }
- }
-
- withContext(Dispatchers.Main) {
- listener.onDownloadEnd(file)
- }
-
- job.cancel()
- }
- }
- }
- })
- }
-
- interface OnFileDownloadListener {
- fun onDownloadStart(total: Long)
- fun onProgressChanged(progress: Long)
- fun onDownloadEnd(file: File)
- fun onFailed(t: Throwable)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt b/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
index 2334680..c658924 100644
--- a/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
@@ -14,10 +14,6 @@
const val PERMISSIONS_CODE = 999
const val MAX_DISTANCE = 5.5f //表盘最大显示距离
- const val FREE_INSPECTION = 20250101
- const val INSTALL_MARKER = 20250102
- const val DETECT_MARKER_DEPTH = 20250103
- const val SEARCH_MARKER = 20250104
const val AUTO_SAVE = "AUTO_SAVE"
const val USER_ACCOUNT = "USER_ACCOUNT"
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt b/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt
deleted file mode 100644
index 104f971..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.casic.common.detector.gd.utils
-
-object RuntimeCache {
- var currentSegment: CurrentSegment? = null
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt
index c5f18a6..b3dce3c 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt
@@ -1,26 +1,19 @@
package com.casic.common.detector.gd.view
import android.app.DatePickerDialog
-import android.content.ComponentName
-import android.content.Context
import android.content.DialogInterface
-import android.content.Intent
-import android.content.ServiceConnection
import android.hardware.Camera
import android.media.AudioAttributes
import android.media.SoundPool
import android.os.Bundle
import android.os.CountDownTimer
-import android.os.Handler
-import android.os.IBinder
-import android.os.Message
-import android.util.Log
import android.view.View
import android.widget.AdapterView
import androidx.lifecycle.ViewModelProvider
import com.amap.api.location.AMapLocation
import com.casic.common.detector.gd.R
import com.casic.common.detector.gd.adapter.EditableImageAdapter
+import com.casic.common.detector.gd.base.SerialPortActivity
import com.casic.common.detector.gd.bean.MarkerLocalBean
import com.casic.common.detector.gd.callback.OnGetLocationListener
import com.casic.common.detector.gd.callback.OnImageCompressListener
@@ -33,18 +26,15 @@
import com.casic.common.detector.gd.extensions.toColor
import com.casic.common.detector.gd.extensions.toMarkerId
import com.casic.common.detector.gd.extensions.toObjectType
-import com.casic.common.detector.gd.service.SerialPortService
import com.casic.common.detector.gd.utils.CurrentSegment
import com.casic.common.detector.gd.utils.DataBaseManager
import com.casic.common.detector.gd.utils.LocaleConstant
import com.casic.common.detector.gd.utils.LocationKit
-import com.casic.common.detector.gd.utils.RuntimeCache
import com.casic.common.detector.gd.vm.TaskViewModel
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.appendZero
import com.pengxh.kt.lite.extensions.dateToTimestamp
import com.pengxh.kt.lite.extensions.navigatePageTo
@@ -55,13 +45,12 @@
import com.pengxh.kt.lite.utils.LoadState
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.utils.SaveKeyValues
-import com.pengxh.kt.lite.utils.WeakReferenceHandler
import com.pengxh.kt.lite.widget.TitleBarView
import java.io.File
import java.util.Calendar
import java.util.Date
-class InstallMarkerActivity : KotlinBaseActivity(), Handler.Callback {
+class InstallMarkerActivity : SerialPortActivity() {
private val kTag = "InstallMarkerActivity"
private val context = this
@@ -73,7 +62,6 @@
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build()
private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build()
private var soundResourceId = 0
- private var serialPortService: SerialPortService? = null
private lateinit var imageAdapter: EditableImageAdapter
override fun initEvent() {
@@ -255,18 +243,18 @@
//读标识器
binding.readMarkerButton.setOnClickListener {
+ openSerialPort()
LoadingDialog.show(this, "标识器读取中,请稍后...")
countDownTimer.start()
binding.readMarkerButton.isEnabled = false
- RuntimeCache.currentSegment = CurrentSegment.InstallMarker
- serialPortService?.writeCommand('2')
+ readMarkerId()
}
}
- override fun handleMessage(msg: Message): Boolean {
- if (msg.what == LocaleConstant.INSTALL_MARKER) {
- val buffer = msg.obj as ByteArray
- if ((buffer.first().toInt() and 0xFF).toString(16).uppercase() == "30") {
+ override fun onDataReceived(buffer: ByteArray, segment: CurrentSegment) {
+ if (segment == CurrentSegment.InstallMarker) {
+ val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase()
+ if (flag == "30" && buffer.size == 10) {
val markerId = buffer.toMarkerId()
LoadingDialog.dismiss()
countDownTimer.cancel()
@@ -274,7 +262,6 @@
binding.identifierInclude.identifierIdView.text = markerId
}
}
- return true
}
/**
@@ -363,37 +350,7 @@
})
}
- private val serviceConnection = object : ServiceConnection {
- override fun onServiceConnected(name: ComponentName?, iBinder: IBinder?) {
- if (name != null && iBinder != null && iBinder is SerialPortService.ServiceBinder) {
- try {
- serialPortService = iBinder.getSerialPortService()
- Log.d(kTag, "onServiceConnected: 服务已绑定")
- } catch (e: Exception) {
- Log.e(kTag, "onServiceConnected: 绑定服务时发生异常", e)
- }
- } else {
- Log.w(kTag, "onServiceConnected: name 或 iBinder 为 null")
- }
- }
-
- override fun onServiceDisconnected(name: ComponentName?) {
- //在连接正常关闭的情况下不会被调用, 只在Service被破坏了或者被杀死的时候调用
- }
- }
-
- companion object {
- var weakReferenceHandler: WeakReferenceHandler? = null
- }
-
override fun initOnCreate(savedInstanceState: Bundle?) {
- weakReferenceHandler = WeakReferenceHandler(this)
-
- //绑定串口通信服务
- Intent(this, SerialPortService::class.java).also {
- bindService(it, serviceConnection, Context.BIND_AUTO_CREATE)
- }
-
locationKit.getCurrentLocation(true, object : OnGetLocationListener {
override fun onSuccess(location: AMapLocation) {
binding.identifierInclude.lngView.text = location.longitude.toString()
@@ -552,8 +509,6 @@
override fun onDestroy() {
super.onDestroy()
- RuntimeCache.currentSegment = null
locationKit.stopLocation()
- unbindService(serviceConnection)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt
index 8a798b6..2c48cc9 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt
@@ -1,18 +1,12 @@
package com.casic.common.detector.gd.view
import android.app.Activity
-import android.content.ComponentName
-import android.content.Context
import android.content.Intent
-import android.content.ServiceConnection
import android.graphics.BitmapFactory
import android.graphics.Color
import android.media.AudioAttributes
import android.media.SoundPool
import android.os.Bundle
-import android.os.Handler
-import android.os.IBinder
-import android.os.Message
import android.util.Log
import android.view.KeyEvent
import android.view.View
@@ -34,6 +28,7 @@
import com.amap.api.maps.model.MyLocationStyle
import com.casic.common.detector.gd.R
import com.casic.common.detector.gd.base.BaseApplication
+import com.casic.common.detector.gd.base.SerialPortActivity
import com.casic.common.detector.gd.bean.MarkerLocalBean
import com.casic.common.detector.gd.bean.TaskLocalBean
import com.casic.common.detector.gd.callback.OnGetAddressListener
@@ -47,32 +42,27 @@
import com.casic.common.detector.gd.model.TaskDetailLocalModel
import com.casic.common.detector.gd.model.TaskModel
import com.casic.common.detector.gd.service.NtripConnectService
-import com.casic.common.detector.gd.service.SerialPortService
import com.casic.common.detector.gd.utils.CurrentSegment
import com.casic.common.detector.gd.utils.DataBaseManager
import com.casic.common.detector.gd.utils.ExcelKit
-import com.casic.common.detector.gd.utils.FileDownloadManager
import com.casic.common.detector.gd.utils.FileType
-import com.casic.common.detector.gd.utils.GpioManager
import com.casic.common.detector.gd.utils.LocaleConstant
import com.casic.common.detector.gd.utils.LocationKit
import com.casic.common.detector.gd.utils.RouteOnMap
-import com.casic.common.detector.gd.utils.RuntimeCache
import com.casic.common.detector.gd.vm.TaskViewModel
import com.casic.common.detector.gd.widgets.MarkerDetailDialog
import com.casic.common.detector.gd.widgets.QueryMarkerDialog
import com.casic.common.detector.gd.widgets.SamplePopupWindow
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.createDownloadFileDir
import com.pengxh.kt.lite.extensions.dp2px
import com.pengxh.kt.lite.extensions.isNetworkConnected
import com.pengxh.kt.lite.extensions.navigatePageTo
import com.pengxh.kt.lite.extensions.show
import com.pengxh.kt.lite.extensions.timestampToCompleteDate
+import com.pengxh.kt.lite.utils.FileDownloadManager
import com.pengxh.kt.lite.utils.LoadState
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.utils.SaveKeyValues
-import com.pengxh.kt.lite.utils.WeakReferenceHandler
import com.pengxh.kt.lite.widget.TitleBarView
import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
import com.pengxh.kt.lite.widget.dialog.AlertInputDialog
@@ -82,45 +72,13 @@
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
-import java.util.concurrent.atomic.AtomicInteger
-class MainActivity : KotlinBaseActivity(), AMap.OnMarkerClickListener,
- OnMapLongClickListener, Handler.Callback {
+class MainActivity : SerialPortActivity(), AMap.OnMarkerClickListener,
+ OnMapLongClickListener {
private val kTag = "MainActivity"
private val context = this
-
- /***************************************************************************************/
- private val gpioManager by lazy { GpioManager() }
-
- /**
- * 读取数据 1
- * 暂停读取 0
- * */
- private val gpioState = AtomicInteger(0)
- private fun openSerialPort() {
- if (gpioState.get() != 1) {
- gpioManager.setGpioHigh("18")
- gpioState.set(1)
- Log.d(kTag, "openSerialPort: 调高串口电位")
- } else {
- Log.d(kTag, "openSerialPort: 已经是高电位,直接读数据")
- }
- }
-
- private fun closeSerialPort() {
- if (gpioState.get() == 0) {
- Log.d(kTag, "closeSerialPort: 已经是低电位,直接返回")
- return
- }
- // 降低串口电位
- gpioManager.setGpioLow("18")
- gpioState.set(0)
- Log.d(kTag, "closeSerialPort: 降低串口电位")
- }
-
- /***************************************************************************************/
private val samplePopupWindow by lazy { SamplePopupWindow(this) }
private val detailDialog by lazy { MarkerDetailDialog(this) }
private val locationKit by lazy { LocationKit(this) }
@@ -133,7 +91,6 @@
private var freeTaskTitle = ""
private var ids = HashSet()
private var freeTaskId: String? = null
- private var serialPortService: SerialPortService? = null
private var soundResourceId = 0
private var isExecuteTask = false
private lateinit var aMap: AMap
@@ -146,43 +103,13 @@
binding.rootView.initImmersionBar(this, false, R.color.themeColor)
}
- private val serviceConnection = object : ServiceConnection {
- override fun onServiceConnected(name: ComponentName?, iBinder: IBinder?) {
- if (name != null && iBinder != null && iBinder is SerialPortService.ServiceBinder) {
- try {
- serialPortService = iBinder.getSerialPortService()
- Log.d(kTag, "onServiceConnected: 服务已绑定")
- openSerialPort()
- } catch (e: Exception) {
- Log.e(kTag, "onServiceConnected: 绑定服务时发生异常", e)
- }
- } else {
- Log.w(kTag, "onServiceConnected: name 或 iBinder 为 null")
- }
- }
-
- override fun onServiceDisconnected(name: ComponentName?) {
-
- }
- }
-
- companion object {
- var weakReferenceHandler: WeakReferenceHandler? = null
- }
-
override fun initOnCreate(savedInstanceState: Bundle?) {
- weakReferenceHandler = WeakReferenceHandler(this)
-
//地图初始化
initMapConfig(savedInstanceState)
- //绑定串口通信服务
- Intent(this, SerialPortService::class.java).also {
- bindService(it, serviceConnection, Context.BIND_AUTO_CREATE)
- }
- Intent(this, NtripConnectService::class.java).also {
- startService(it)
- }
+// Intent(this, NtripConnectService::class.java).also {
+// startService(it)
+// }
soundResourceId = soundPool.load(this, R.raw.ring3, 1)
//右上角菜单
@@ -211,7 +138,7 @@
showMarkersOnMap()
}
- override fun onFailed(t: Throwable) {
+ override fun onDownloadFailed(t: Throwable) {
t.printStackTrace()
}
@@ -446,7 +373,7 @@
override fun onConfirmClick() {
isFreeTask = false
soundPool.autoPause()
- RuntimeCache.currentSegment = null
+ closeSerialPort()
binding.stopFreeTaskButton.visibility = View.GONE
if (freeTaskId.isNullOrBlank()) {
@@ -499,11 +426,7 @@
} else {
"此工单下无标识器,将执行自由巡检任务".show(context)
freeTaskId = task.taskId
-
- binding.stopFreeTaskButton.visibility = View.VISIBLE
- isFreeTask = true
- RuntimeCache.currentSegment = CurrentSegment.FreeInspection
- serialPortService?.writeCommand('2', '6')
+ detectMarker()
}
}
@@ -524,21 +447,22 @@
freeTaskTitle = value
val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String
taskViewModel.createFreeTask(context, userId, value)
-
- binding.stopFreeTaskButton.visibility = View.VISIBLE
- isFreeTask = true
- RuntimeCache.currentSegment = CurrentSegment.FreeInspection
- serialPortService?.writeCommand('2', '6')
+ detectMarker()
}
override fun onCancelClick() {}
}).build().show()
}
- override fun handleMessage(msg: Message): Boolean {
- if (msg.what == LocaleConstant.FREE_INSPECTION) {
- val buffer = msg.obj as ByteArray
- //只响一次,因为探测频率高,所以依旧是连续的报警声
+ private fun detectMarker() {
+ binding.stopFreeTaskButton.visibility = View.VISIBLE
+ isFreeTask = true
+ openSerialPort()
+ searchMarker(CurrentSegment.FreeInspection)
+ }
+
+ override fun onDataReceived(buffer: ByteArray, segment: CurrentSegment) {
+ if (segment == CurrentSegment.FreeInspection) {
soundPool.play(soundResourceId, 1f, 1f, 0, 0, 1f)
when ((buffer.first().toInt() and 0xFF).toString(16).uppercase()) {
"4E" -> {
@@ -552,27 +476,30 @@
val markerId = buffer.toMarkerId()
//添加地图Marker
if (!ids.contains(markerId)) {
- //根据markerId查询标识器经纬度
- val labels = DataBaseManager.get.queryMarkerById(markerId)
- if (labels.isNotEmpty()) {
- val bean = labels.first()
- aMap.addMarker(
- MarkerOptions()
- .position(LatLng(bean.lat.toDouble(), bean.lng.toDouble()))
- .icon(BitmapDescriptorFactory.fromResource(R.mipmap.label_blue1))
+ val markers = DataBaseManager.get.queryMarkerById(markerId)
+ if (markers.isNotEmpty()) {
+ val marker = markers.first()
+ val latLng = LatLng(
+ marker.lat.toDouble(), marker.lng.toDouble()
)
+ val resource = BitmapDescriptorFactory.fromResource(
+ R.mipmap.label_blue1
+ )
+ val options = MarkerOptions().position(latLng).icon(resource)
+ aMap.addMarker(options)
}
}
ids.add(markerId)
//显示标识器详细信息
if (!detailDialog.isShowing) {
- val markerBean = DataBaseManager.get.queryMarkerById(markerId).firstOrNull()
- if (markerBean == null) {
- "无法查询到此ID【${markerId}】的信息".show(context)
- } else {
- detailDialog.setMarker(markerBean)
- detailDialog.show()
+ DataBaseManager.get.queryMarkerById(markerId).firstOrNull().apply {
+ if (this == null) {
+ "无法查询到此ID【${markerId}】的信息".show(context)
+ } else {
+ detailDialog.setMarker(this)
+ detailDialog.show()
+ }
}
}
}
@@ -582,7 +509,6 @@
}
}
}
- return true
}
override fun observeRequestState() {
@@ -865,9 +791,6 @@
override fun onResume() {
super.onResume()
binding.mapView.onResume()
- if (serialPortService != null) {
- openSerialPort()
- }
}
override fun onPause() {
@@ -885,8 +808,6 @@
binding.mapView.onDestroy()
soundPool.autoPause()
locationKit.stopLocation()
- unbindService(serviceConnection)
- closeSerialPort()
BaseApplication.get().closeSerialPort()
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/SatelliteStatusActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/SatelliteStatusActivity.kt
index 9f2d5cd..0f1611d 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/SatelliteStatusActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/SatelliteStatusActivity.kt
@@ -74,7 +74,7 @@
locationManager.registerGnssStatusCallback(gnssStatusListener, null)
satelliteAdapter = SatelliteRecyclerAdapter(this, satelliteCollection)
binding.recyclerView.adapter = satelliteAdapter
- binding.recyclerView.addItemDecoration(RecyclerViewItemDivider(1, Color.WHITE))
+ binding.recyclerView.addItemDecoration(RecyclerViewItemDivider(0f, 0f, Color.WHITE))
//高德定位
locationKit.getCurrentLocation(false, object : OnGetLocationListener {
diff --git a/app/build.gradle b/app/build.gradle
index c9b11ec..1a81160 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -77,7 +77,7 @@
dependencies {
//基础依赖库
- implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1'
+ implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.3'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
//Google官方授权框架
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2f152d8..5c645f0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -91,7 +91,6 @@
android:resource="@xml/file_paths" />
-
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
index 6cb496c..e5fe1f5 100644
--- a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
@@ -1,6 +1,7 @@
package com.casic.common.detector.gd.base
import android.app.Application
+import android.util.Log
import com.casic.common.detector.gd.greendao.DaoMaster
import com.casic.common.detector.gd.greendao.DaoSession
import com.casic.common.detector.gd.uart.SerialPort
@@ -52,6 +53,7 @@
//千寻报文数据下发串口号
add(SerialPort(File("/dev/ttyS1"), 9600, 0))
}
+ Log.d(kTag, "onCreate: 已初始化 ${serialPorts.size} 个串口")
} catch (e: SecurityException) {
"您没有串口的读写权限!".show(this)
} catch (e: IOException) {
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
new file mode 100644
index 0000000..08b3e19
--- /dev/null
+++ b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
@@ -0,0 +1,204 @@
+package com.casic.common.detector.gd.base
+
+import android.os.Bundle
+import android.os.Handler
+import android.os.Message
+import android.util.Log
+import androidx.appcompat.app.AppCompatActivity
+import androidx.viewbinding.ViewBinding
+import com.casic.common.detector.gd.utils.CurrentSegment
+import com.casic.common.detector.gd.utils.GpioManager
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import java.io.IOException
+import java.util.Timer
+import java.util.TimerTask
+import java.util.concurrent.atomic.AtomicInteger
+
+abstract class SerialPortActivity : AppCompatActivity(), Handler.Callback {
+
+ private val kTag = "SerialPortActivity"
+ private val taskTimer by lazy { Timer() }
+ private val weakReferenceHandler by lazy { WeakReferenceHandler(this) }
+
+ //输出流
+ private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
+
+ //输入流
+ private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
+ private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
+
+ private var segment: CurrentSegment? = null
+
+ protected lateinit var binding: VB
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = initViewBinding()
+ setContentView(binding.root)
+ setupTopBarLayout()
+ initOnCreate(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = firstInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = lastInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+ }
+
+ /**
+ * 初始化ViewBinding
+ */
+ abstract fun initViewBinding(): VB
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initOnCreate(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ abstract fun onDataReceived(buffer: ByteArray, segment: CurrentSegment)
+
+ override fun handleMessage(msg: Message): Boolean {
+ if (msg.what == 2025012001) {
+ val bytes = msg.obj as ByteArray
+ if (segment == null) {
+ return true
+ }
+ Log.d(kTag, "$segment - ${bytes.contentToString()}")
+ onDataReceived(bytes, segment!!)
+ }
+ return true
+ }
+
+ private var readMarkerIdTask: TimerTask? = null
+ private var searchMarkerTask: TimerTask? = null
+
+ fun readMarkerId() {
+ this.segment = CurrentSegment.InstallMarker
+ readMarkerIdTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(readMarkerIdTask, 0, 300)
+ }
+
+ fun detectDepth(tag: Char) {
+ this.segment = CurrentSegment.DetectDepth
+ outStream.write('3'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write(tag.code)
+ outStream.flush()
+ }
+
+ fun updateSegment(segment: CurrentSegment) {
+ this.segment = segment
+ }
+
+ fun searchMarker(segment: CurrentSegment) {
+ this.segment = segment
+ searchMarkerTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write('6'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(searchMarkerTask, 0, 300)
+ }
+
+ /***************************************************************************************/
+ private val gpioManager by lazy { GpioManager() }
+
+ /**
+ * 读取数据 1
+ * 暂停读取 0
+ * */
+ private val gpioState = AtomicInteger(0)
+ fun openSerialPort() {
+ if (gpioState.get() != 1) {
+ gpioManager.setGpioHigh("18")
+ gpioState.set(1)
+ Log.d(kTag, "openSerialPort: 调高串口电位")
+ } else {
+ Log.d(kTag, "openSerialPort: 已经是高电位,直接读数据")
+ }
+ }
+
+ fun closeSerialPort() {
+ if (segment != null) {
+ segment = null
+ }
+ readMarkerIdTask?.cancel()
+ searchMarkerTask?.cancel()
+ if (gpioState.get() == 0) {
+ Log.d(kTag, "closeSerialPort: 已经是低电位,不响应")
+ return
+ }
+ // 降低串口电位
+ gpioManager.setGpioLow("18")
+ gpioState.set(0)
+ Log.d(kTag, "closeSerialPort: 降低串口电位")
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ closeSerialPort()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
index 442189e..5c3ee01 100644
--- a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
@@ -1,42 +1,20 @@
package com.casic.common.detector.gd.extensions
-import android.util.Log
-
/**
* 因为数据频率很高,而且每一帧数据至少有一个信号值,如果有多个信号强度值,取平均值
*
* [78, 53, 49, 55, 51]
*
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
* */
fun ByteArray.toSignalStrength(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var strength = 0
+ for (byte in dataBytes) {
+ strength = strength * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return strength
}
/**
@@ -44,32 +22,13 @@
*
* [48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
*
- * [48, 48, 48, 56, 56, 57, 49, 48, 55, 51, 48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
- *
* */
fun ByteArray.toMarkerId(): String {
- //判断数据合理性
- val validBytes = if (this.size % 10 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 10) * 10
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ val id = this.map { it.toInt().toChar() }.joinToString("")
+ if (id.matches("-?\\d+".toRegex())) {
+ return id
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 10) {
- // 每10个字节取一次数据转为ASCII
- val tempBytes = validBytes.sliceArray(i until minOf(i + 10, validBytes.size))
- val string = tempBytes.map { it.toInt().toChar() }.joinToString("")
- if (string.matches("-?\\d+".toRegex())) {
- list.add(string)
- } else {
- Log.d("kTag", "toDeviceCode: 编号解析失败")
- }
- }
- return list.last()
+ return ""
}
/**
@@ -77,31 +36,14 @@
*
* [83, 48, 48, 48, 57]
*
- * [83, 48, 48, 48, 57, 83, 48, 48, 48, 57]
* */
fun ByteArray.toBuryDepth(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var depth = 0
+ for (byte in dataBytes) {
+ depth = depth * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return depth
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt b/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
deleted file mode 100644
index 76cf583..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
+++ /dev/null
@@ -1,136 +0,0 @@
-package com.casic.common.detector.gd.service
-
-import android.app.Service
-import android.content.Intent
-import android.os.Binder
-import android.os.IBinder
-import android.util.Log
-import com.casic.common.detector.gd.base.BaseApplication
-import com.casic.common.detector.gd.utils.CurrentSegment
-import com.casic.common.detector.gd.utils.LocaleConstant
-import com.casic.common.detector.gd.utils.RuntimeCache
-import com.casic.common.detector.gd.view.InstallMarkerActivity
-import com.casic.common.detector.gd.view.MainActivity
-import com.casic.common.detector.gd.view.SearchMarkerActivity
-import java.io.IOException
-import java.io.InputStream
-import java.util.concurrent.Executors
-import java.util.concurrent.TimeUnit
-
-class SerialPortService : Service() {
-
- private val kTag = "SerialPortService"
- private val sendExecutor = Executors.newFixedThreadPool(5)
- private val readExecutor = Executors.newSingleThreadScheduledExecutor()
-
- //输出流
- private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
-
- //输入流
- private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
- private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
-
- override fun onCreate() {
- super.onCreate()
- try {
- // 使用单线程调度器读取数据
- readExecutor.scheduleAtFixedRate({
- readData(firstInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
-
- readExecutor.scheduleAtFixedRate({
- readData(lastInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- private fun readData(inputStream: InputStream) {
- try {
- val buffer = ByteArray(1024)
- var bytesRead: Int
- while (inputStream.available() > 0) {
- bytesRead = inputStream.read(buffer)
- if (bytesRead > 0) {
- when (RuntimeCache.currentSegment) {
- CurrentSegment.DetectMarkerDepth -> {
- //深度
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.DETECT_MARKER_DEPTH
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.InstallMarker -> {
- //安装点
- InstallMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.INSTALL_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.FreeInspection -> {
- //自由巡检
- MainActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.FREE_INSPECTION
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.SearchMarker -> {
- //搜索标识器
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.SEARCH_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- else -> {
- val bytes = buffer.copyOf(bytesRead)
- Log.d(kTag, "空状态,不处理 ===> ${bytes.contentToString()}")
- }
- }
- }
- }
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- fun writeCommand(vararg command: Char) {
- Log.d(kTag, "writeCommand: ${command.contentToString()}")
- if (command.size == 1) {
- sendExecutor.submit {
- outStream.write(command.first().code)
- outStream.flush()
- }
- } else {
- command.forEach {
- sendExecutor.submit {
- outStream.write(it.code)
- outStream.flush()
- }
- Thread.sleep(1000)
- }
- }
- }
-
- override fun onBind(intent: Intent?): IBinder {
- return ServiceBinder()
- }
-
- inner class ServiceBinder : Binder() {
- fun getSerialPortService(): SerialPortService {
- return this@SerialPortService
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt b/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
index 0606b72..9efa097 100644
--- a/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
@@ -1,23 +1,23 @@
package com.casic.common.detector.gd.utils
-sealed class CurrentSegment {
+enum class CurrentSegment {
/**
* 安装标识器
* */
- object InstallMarker : CurrentSegment()
+ InstallMarker,
/**
* 自由巡检
* */
- object FreeInspection : CurrentSegment()
+ FreeInspection,
/**
* 搜索标识器
* */
- object SearchMarker : CurrentSegment()
+ SearchMarker,
/**
* 探测标识器深度
* */
- object DetectMarkerDepth : CurrentSegment()
+ DetectDepth
}
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt
deleted file mode 100644
index c9151a8..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt
+++ /dev/null
@@ -1,150 +0,0 @@
-package com.casic.common.detector.gd.utils
-
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.SupervisorJob
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import okhttp3.Call
-import okhttp3.Callback
-import okhttp3.OkHttpClient
-import okhttp3.Request
-import okhttp3.Response
-import java.io.File
-import java.io.IOException
-import java.util.concurrent.atomic.AtomicBoolean
-
-class FileDownloadManager(builder: Builder) {
-
- private val httpClient by lazy { OkHttpClient() }
-
- class Builder {
- lateinit var url: String
- lateinit var suffix: String
- lateinit var directory: File
- lateinit var downloadListener: OnFileDownloadListener
-
- /**
- * 文件下载地址
- * */
- fun setDownloadFileSource(url: String): Builder {
- this.url = url
- return this
- }
-
- /**
- * 文件后缀
- * 如:apk等
- * */
- fun setFileSuffix(suffix: String): Builder {
- this.suffix = if (suffix.contains(".")) {
- //去掉前缀的点
- suffix.drop(1)
- } else {
- suffix
- }
- return this
- }
-
- /**
- * 文件保存的地址
- * */
- fun setFileSaveDirectory(directory: File): Builder {
- this.directory = directory
- return this
- }
-
- /**
- * 设置文件下载回调监听
- * */
- fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder {
- this.downloadListener = downloadListener
- return this
- }
-
- fun build(): FileDownloadManager {
- if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) {
- throw IllegalStateException("All properties must be initialized before building.")
- }
- return FileDownloadManager(this)
- }
- }
-
- private val url = builder.url
- private val suffix = builder.suffix
- private val directory = builder.directory
- private val listener = builder.downloadListener
-
- /**
- * 开始下载
- * */
- fun start() {
- val job = SupervisorJob()
- val scope = CoroutineScope(Dispatchers.Main + job)
-
- val request = Request.Builder().get().url(url).build()
- val newCall = httpClient.newCall(request)
- val isExecuting = AtomicBoolean(false)
-
- /**
- * 如果已被加入下载队列,则取消之前的,重新下载
- */
- if (isExecuting.getAndSet(true)) {
- newCall.cancel()
- }
-
- //异步下载文件
- newCall.enqueue(object : Callback {
- override fun onFailure(call: Call, e: IOException) {
- scope.launch(Dispatchers.Main) {
- listener.onFailed(e)
- }
- }
-
- override fun onResponse(call: Call, response: Response) {
- scope.launch(Dispatchers.IO) {
- val body = response.body
- if (body == null) {
- listener.onFailed(IOException("Response body is null"))
- throw IOException("Response body is null")
- } else {
- val inputStream = body.byteStream()
- val fileSize = body.contentLength()
-
- if (fileSize <= 0) {
- throw IllegalArgumentException("Invalid file size")
- }
- listener.onDownloadStart(fileSize)
-
- val file = File(directory, "${System.currentTimeMillis()}.${suffix}")
- file.outputStream().use { fos ->
- val buffer = ByteArray(2048)
- var sum = 0L
- var read: Int
- while (inputStream.read(buffer).also { read = it } != -1) {
- fos.write(buffer, 0, read)
- sum += read.toLong()
- withContext(Dispatchers.Main) {
- listener.onProgressChanged(sum)
- }
- }
- }
-
- withContext(Dispatchers.Main) {
- listener.onDownloadEnd(file)
- }
-
- job.cancel()
- }
- }
- }
- })
- }
-
- interface OnFileDownloadListener {
- fun onDownloadStart(total: Long)
- fun onProgressChanged(progress: Long)
- fun onDownloadEnd(file: File)
- fun onFailed(t: Throwable)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt b/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
index 2334680..c658924 100644
--- a/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
@@ -14,10 +14,6 @@
const val PERMISSIONS_CODE = 999
const val MAX_DISTANCE = 5.5f //表盘最大显示距离
- const val FREE_INSPECTION = 20250101
- const val INSTALL_MARKER = 20250102
- const val DETECT_MARKER_DEPTH = 20250103
- const val SEARCH_MARKER = 20250104
const val AUTO_SAVE = "AUTO_SAVE"
const val USER_ACCOUNT = "USER_ACCOUNT"
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt b/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt
deleted file mode 100644
index 104f971..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.casic.common.detector.gd.utils
-
-object RuntimeCache {
- var currentSegment: CurrentSegment? = null
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt
index c5f18a6..b3dce3c 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt
@@ -1,26 +1,19 @@
package com.casic.common.detector.gd.view
import android.app.DatePickerDialog
-import android.content.ComponentName
-import android.content.Context
import android.content.DialogInterface
-import android.content.Intent
-import android.content.ServiceConnection
import android.hardware.Camera
import android.media.AudioAttributes
import android.media.SoundPool
import android.os.Bundle
import android.os.CountDownTimer
-import android.os.Handler
-import android.os.IBinder
-import android.os.Message
-import android.util.Log
import android.view.View
import android.widget.AdapterView
import androidx.lifecycle.ViewModelProvider
import com.amap.api.location.AMapLocation
import com.casic.common.detector.gd.R
import com.casic.common.detector.gd.adapter.EditableImageAdapter
+import com.casic.common.detector.gd.base.SerialPortActivity
import com.casic.common.detector.gd.bean.MarkerLocalBean
import com.casic.common.detector.gd.callback.OnGetLocationListener
import com.casic.common.detector.gd.callback.OnImageCompressListener
@@ -33,18 +26,15 @@
import com.casic.common.detector.gd.extensions.toColor
import com.casic.common.detector.gd.extensions.toMarkerId
import com.casic.common.detector.gd.extensions.toObjectType
-import com.casic.common.detector.gd.service.SerialPortService
import com.casic.common.detector.gd.utils.CurrentSegment
import com.casic.common.detector.gd.utils.DataBaseManager
import com.casic.common.detector.gd.utils.LocaleConstant
import com.casic.common.detector.gd.utils.LocationKit
-import com.casic.common.detector.gd.utils.RuntimeCache
import com.casic.common.detector.gd.vm.TaskViewModel
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.appendZero
import com.pengxh.kt.lite.extensions.dateToTimestamp
import com.pengxh.kt.lite.extensions.navigatePageTo
@@ -55,13 +45,12 @@
import com.pengxh.kt.lite.utils.LoadState
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.utils.SaveKeyValues
-import com.pengxh.kt.lite.utils.WeakReferenceHandler
import com.pengxh.kt.lite.widget.TitleBarView
import java.io.File
import java.util.Calendar
import java.util.Date
-class InstallMarkerActivity : KotlinBaseActivity(), Handler.Callback {
+class InstallMarkerActivity : SerialPortActivity() {
private val kTag = "InstallMarkerActivity"
private val context = this
@@ -73,7 +62,6 @@
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build()
private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build()
private var soundResourceId = 0
- private var serialPortService: SerialPortService? = null
private lateinit var imageAdapter: EditableImageAdapter
override fun initEvent() {
@@ -255,18 +243,18 @@
//读标识器
binding.readMarkerButton.setOnClickListener {
+ openSerialPort()
LoadingDialog.show(this, "标识器读取中,请稍后...")
countDownTimer.start()
binding.readMarkerButton.isEnabled = false
- RuntimeCache.currentSegment = CurrentSegment.InstallMarker
- serialPortService?.writeCommand('2')
+ readMarkerId()
}
}
- override fun handleMessage(msg: Message): Boolean {
- if (msg.what == LocaleConstant.INSTALL_MARKER) {
- val buffer = msg.obj as ByteArray
- if ((buffer.first().toInt() and 0xFF).toString(16).uppercase() == "30") {
+ override fun onDataReceived(buffer: ByteArray, segment: CurrentSegment) {
+ if (segment == CurrentSegment.InstallMarker) {
+ val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase()
+ if (flag == "30" && buffer.size == 10) {
val markerId = buffer.toMarkerId()
LoadingDialog.dismiss()
countDownTimer.cancel()
@@ -274,7 +262,6 @@
binding.identifierInclude.identifierIdView.text = markerId
}
}
- return true
}
/**
@@ -363,37 +350,7 @@
})
}
- private val serviceConnection = object : ServiceConnection {
- override fun onServiceConnected(name: ComponentName?, iBinder: IBinder?) {
- if (name != null && iBinder != null && iBinder is SerialPortService.ServiceBinder) {
- try {
- serialPortService = iBinder.getSerialPortService()
- Log.d(kTag, "onServiceConnected: 服务已绑定")
- } catch (e: Exception) {
- Log.e(kTag, "onServiceConnected: 绑定服务时发生异常", e)
- }
- } else {
- Log.w(kTag, "onServiceConnected: name 或 iBinder 为 null")
- }
- }
-
- override fun onServiceDisconnected(name: ComponentName?) {
- //在连接正常关闭的情况下不会被调用, 只在Service被破坏了或者被杀死的时候调用
- }
- }
-
- companion object {
- var weakReferenceHandler: WeakReferenceHandler? = null
- }
-
override fun initOnCreate(savedInstanceState: Bundle?) {
- weakReferenceHandler = WeakReferenceHandler(this)
-
- //绑定串口通信服务
- Intent(this, SerialPortService::class.java).also {
- bindService(it, serviceConnection, Context.BIND_AUTO_CREATE)
- }
-
locationKit.getCurrentLocation(true, object : OnGetLocationListener {
override fun onSuccess(location: AMapLocation) {
binding.identifierInclude.lngView.text = location.longitude.toString()
@@ -552,8 +509,6 @@
override fun onDestroy() {
super.onDestroy()
- RuntimeCache.currentSegment = null
locationKit.stopLocation()
- unbindService(serviceConnection)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt
index 8a798b6..2c48cc9 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt
@@ -1,18 +1,12 @@
package com.casic.common.detector.gd.view
import android.app.Activity
-import android.content.ComponentName
-import android.content.Context
import android.content.Intent
-import android.content.ServiceConnection
import android.graphics.BitmapFactory
import android.graphics.Color
import android.media.AudioAttributes
import android.media.SoundPool
import android.os.Bundle
-import android.os.Handler
-import android.os.IBinder
-import android.os.Message
import android.util.Log
import android.view.KeyEvent
import android.view.View
@@ -34,6 +28,7 @@
import com.amap.api.maps.model.MyLocationStyle
import com.casic.common.detector.gd.R
import com.casic.common.detector.gd.base.BaseApplication
+import com.casic.common.detector.gd.base.SerialPortActivity
import com.casic.common.detector.gd.bean.MarkerLocalBean
import com.casic.common.detector.gd.bean.TaskLocalBean
import com.casic.common.detector.gd.callback.OnGetAddressListener
@@ -47,32 +42,27 @@
import com.casic.common.detector.gd.model.TaskDetailLocalModel
import com.casic.common.detector.gd.model.TaskModel
import com.casic.common.detector.gd.service.NtripConnectService
-import com.casic.common.detector.gd.service.SerialPortService
import com.casic.common.detector.gd.utils.CurrentSegment
import com.casic.common.detector.gd.utils.DataBaseManager
import com.casic.common.detector.gd.utils.ExcelKit
-import com.casic.common.detector.gd.utils.FileDownloadManager
import com.casic.common.detector.gd.utils.FileType
-import com.casic.common.detector.gd.utils.GpioManager
import com.casic.common.detector.gd.utils.LocaleConstant
import com.casic.common.detector.gd.utils.LocationKit
import com.casic.common.detector.gd.utils.RouteOnMap
-import com.casic.common.detector.gd.utils.RuntimeCache
import com.casic.common.detector.gd.vm.TaskViewModel
import com.casic.common.detector.gd.widgets.MarkerDetailDialog
import com.casic.common.detector.gd.widgets.QueryMarkerDialog
import com.casic.common.detector.gd.widgets.SamplePopupWindow
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.createDownloadFileDir
import com.pengxh.kt.lite.extensions.dp2px
import com.pengxh.kt.lite.extensions.isNetworkConnected
import com.pengxh.kt.lite.extensions.navigatePageTo
import com.pengxh.kt.lite.extensions.show
import com.pengxh.kt.lite.extensions.timestampToCompleteDate
+import com.pengxh.kt.lite.utils.FileDownloadManager
import com.pengxh.kt.lite.utils.LoadState
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.utils.SaveKeyValues
-import com.pengxh.kt.lite.utils.WeakReferenceHandler
import com.pengxh.kt.lite.widget.TitleBarView
import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
import com.pengxh.kt.lite.widget.dialog.AlertInputDialog
@@ -82,45 +72,13 @@
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
-import java.util.concurrent.atomic.AtomicInteger
-class MainActivity : KotlinBaseActivity(), AMap.OnMarkerClickListener,
- OnMapLongClickListener, Handler.Callback {
+class MainActivity : SerialPortActivity(), AMap.OnMarkerClickListener,
+ OnMapLongClickListener {
private val kTag = "MainActivity"
private val context = this
-
- /***************************************************************************************/
- private val gpioManager by lazy { GpioManager() }
-
- /**
- * 读取数据 1
- * 暂停读取 0
- * */
- private val gpioState = AtomicInteger(0)
- private fun openSerialPort() {
- if (gpioState.get() != 1) {
- gpioManager.setGpioHigh("18")
- gpioState.set(1)
- Log.d(kTag, "openSerialPort: 调高串口电位")
- } else {
- Log.d(kTag, "openSerialPort: 已经是高电位,直接读数据")
- }
- }
-
- private fun closeSerialPort() {
- if (gpioState.get() == 0) {
- Log.d(kTag, "closeSerialPort: 已经是低电位,直接返回")
- return
- }
- // 降低串口电位
- gpioManager.setGpioLow("18")
- gpioState.set(0)
- Log.d(kTag, "closeSerialPort: 降低串口电位")
- }
-
- /***************************************************************************************/
private val samplePopupWindow by lazy { SamplePopupWindow(this) }
private val detailDialog by lazy { MarkerDetailDialog(this) }
private val locationKit by lazy { LocationKit(this) }
@@ -133,7 +91,6 @@
private var freeTaskTitle = ""
private var ids = HashSet()
private var freeTaskId: String? = null
- private var serialPortService: SerialPortService? = null
private var soundResourceId = 0
private var isExecuteTask = false
private lateinit var aMap: AMap
@@ -146,43 +103,13 @@
binding.rootView.initImmersionBar(this, false, R.color.themeColor)
}
- private val serviceConnection = object : ServiceConnection {
- override fun onServiceConnected(name: ComponentName?, iBinder: IBinder?) {
- if (name != null && iBinder != null && iBinder is SerialPortService.ServiceBinder) {
- try {
- serialPortService = iBinder.getSerialPortService()
- Log.d(kTag, "onServiceConnected: 服务已绑定")
- openSerialPort()
- } catch (e: Exception) {
- Log.e(kTag, "onServiceConnected: 绑定服务时发生异常", e)
- }
- } else {
- Log.w(kTag, "onServiceConnected: name 或 iBinder 为 null")
- }
- }
-
- override fun onServiceDisconnected(name: ComponentName?) {
-
- }
- }
-
- companion object {
- var weakReferenceHandler: WeakReferenceHandler? = null
- }
-
override fun initOnCreate(savedInstanceState: Bundle?) {
- weakReferenceHandler = WeakReferenceHandler(this)
-
//地图初始化
initMapConfig(savedInstanceState)
- //绑定串口通信服务
- Intent(this, SerialPortService::class.java).also {
- bindService(it, serviceConnection, Context.BIND_AUTO_CREATE)
- }
- Intent(this, NtripConnectService::class.java).also {
- startService(it)
- }
+// Intent(this, NtripConnectService::class.java).also {
+// startService(it)
+// }
soundResourceId = soundPool.load(this, R.raw.ring3, 1)
//右上角菜单
@@ -211,7 +138,7 @@
showMarkersOnMap()
}
- override fun onFailed(t: Throwable) {
+ override fun onDownloadFailed(t: Throwable) {
t.printStackTrace()
}
@@ -446,7 +373,7 @@
override fun onConfirmClick() {
isFreeTask = false
soundPool.autoPause()
- RuntimeCache.currentSegment = null
+ closeSerialPort()
binding.stopFreeTaskButton.visibility = View.GONE
if (freeTaskId.isNullOrBlank()) {
@@ -499,11 +426,7 @@
} else {
"此工单下无标识器,将执行自由巡检任务".show(context)
freeTaskId = task.taskId
-
- binding.stopFreeTaskButton.visibility = View.VISIBLE
- isFreeTask = true
- RuntimeCache.currentSegment = CurrentSegment.FreeInspection
- serialPortService?.writeCommand('2', '6')
+ detectMarker()
}
}
@@ -524,21 +447,22 @@
freeTaskTitle = value
val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String
taskViewModel.createFreeTask(context, userId, value)
-
- binding.stopFreeTaskButton.visibility = View.VISIBLE
- isFreeTask = true
- RuntimeCache.currentSegment = CurrentSegment.FreeInspection
- serialPortService?.writeCommand('2', '6')
+ detectMarker()
}
override fun onCancelClick() {}
}).build().show()
}
- override fun handleMessage(msg: Message): Boolean {
- if (msg.what == LocaleConstant.FREE_INSPECTION) {
- val buffer = msg.obj as ByteArray
- //只响一次,因为探测频率高,所以依旧是连续的报警声
+ private fun detectMarker() {
+ binding.stopFreeTaskButton.visibility = View.VISIBLE
+ isFreeTask = true
+ openSerialPort()
+ searchMarker(CurrentSegment.FreeInspection)
+ }
+
+ override fun onDataReceived(buffer: ByteArray, segment: CurrentSegment) {
+ if (segment == CurrentSegment.FreeInspection) {
soundPool.play(soundResourceId, 1f, 1f, 0, 0, 1f)
when ((buffer.first().toInt() and 0xFF).toString(16).uppercase()) {
"4E" -> {
@@ -552,27 +476,30 @@
val markerId = buffer.toMarkerId()
//添加地图Marker
if (!ids.contains(markerId)) {
- //根据markerId查询标识器经纬度
- val labels = DataBaseManager.get.queryMarkerById(markerId)
- if (labels.isNotEmpty()) {
- val bean = labels.first()
- aMap.addMarker(
- MarkerOptions()
- .position(LatLng(bean.lat.toDouble(), bean.lng.toDouble()))
- .icon(BitmapDescriptorFactory.fromResource(R.mipmap.label_blue1))
+ val markers = DataBaseManager.get.queryMarkerById(markerId)
+ if (markers.isNotEmpty()) {
+ val marker = markers.first()
+ val latLng = LatLng(
+ marker.lat.toDouble(), marker.lng.toDouble()
)
+ val resource = BitmapDescriptorFactory.fromResource(
+ R.mipmap.label_blue1
+ )
+ val options = MarkerOptions().position(latLng).icon(resource)
+ aMap.addMarker(options)
}
}
ids.add(markerId)
//显示标识器详细信息
if (!detailDialog.isShowing) {
- val markerBean = DataBaseManager.get.queryMarkerById(markerId).firstOrNull()
- if (markerBean == null) {
- "无法查询到此ID【${markerId}】的信息".show(context)
- } else {
- detailDialog.setMarker(markerBean)
- detailDialog.show()
+ DataBaseManager.get.queryMarkerById(markerId).firstOrNull().apply {
+ if (this == null) {
+ "无法查询到此ID【${markerId}】的信息".show(context)
+ } else {
+ detailDialog.setMarker(this)
+ detailDialog.show()
+ }
}
}
}
@@ -582,7 +509,6 @@
}
}
}
- return true
}
override fun observeRequestState() {
@@ -865,9 +791,6 @@
override fun onResume() {
super.onResume()
binding.mapView.onResume()
- if (serialPortService != null) {
- openSerialPort()
- }
}
override fun onPause() {
@@ -885,8 +808,6 @@
binding.mapView.onDestroy()
soundPool.autoPause()
locationKit.stopLocation()
- unbindService(serviceConnection)
- closeSerialPort()
BaseApplication.get().closeSerialPort()
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/SatelliteStatusActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/SatelliteStatusActivity.kt
index 9f2d5cd..0f1611d 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/SatelliteStatusActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/SatelliteStatusActivity.kt
@@ -74,7 +74,7 @@
locationManager.registerGnssStatusCallback(gnssStatusListener, null)
satelliteAdapter = SatelliteRecyclerAdapter(this, satelliteCollection)
binding.recyclerView.adapter = satelliteAdapter
- binding.recyclerView.addItemDecoration(RecyclerViewItemDivider(1, Color.WHITE))
+ binding.recyclerView.addItemDecoration(RecyclerViewItemDivider(0f, 0f, Color.WHITE))
//高德定位
locationKit.getCurrentLocation(false, object : OnGetLocationListener {
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt
index c7c8bb9..5417e1f 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt
@@ -1,9 +1,5 @@
package com.casic.common.detector.gd.view
-import android.content.ComponentName
-import android.content.Context
-import android.content.Intent
-import android.content.ServiceConnection
import android.graphics.Color
import android.hardware.Sensor
import android.hardware.SensorEvent
@@ -13,9 +9,6 @@
import android.media.SoundPool
import android.os.Bundle
import android.os.CountDownTimer
-import android.os.Handler
-import android.os.IBinder
-import android.os.Message
import android.util.Log
import android.view.View
import android.view.WindowManager
@@ -25,28 +18,25 @@
import com.amap.api.maps.AMapUtils
import com.amap.api.maps.model.LatLng
import com.casic.common.detector.gd.R
+import com.casic.common.detector.gd.base.SerialPortActivity
import com.casic.common.detector.gd.callback.OnGetLocationListener
import com.casic.common.detector.gd.databinding.ActivitySearchMarkerBinding
import com.casic.common.detector.gd.extensions.toBuryDepth
import com.casic.common.detector.gd.extensions.toMarkerId
import com.casic.common.detector.gd.extensions.toSignalStrength
import com.casic.common.detector.gd.model.MarkerDistanceData
-import com.casic.common.detector.gd.service.SerialPortService
import com.casic.common.detector.gd.utils.CurrentSegment
import com.casic.common.detector.gd.utils.DataBaseManager
import com.casic.common.detector.gd.utils.LocaleConstant
import com.casic.common.detector.gd.utils.LocationKit
-import com.casic.common.detector.gd.utils.RuntimeCache
import com.casic.common.detector.gd.vm.TaskViewModel
import com.casic.common.detector.gd.widgets.RadarScanView
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.getSystemService
import com.pengxh.kt.lite.extensions.navigatePageTo
import com.pengxh.kt.lite.extensions.show
import com.pengxh.kt.lite.utils.LiteKitConstant
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.utils.SaveKeyValues
-import com.pengxh.kt.lite.utils.WeakReferenceHandler
import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -55,8 +45,8 @@
import java.util.TimerTask
import kotlin.math.atan2
-class SearchMarkerActivity : KotlinBaseActivity(),
- SensorEventListener, Handler.Callback {
+class SearchMarkerActivity : SerialPortActivity(),
+ SensorEventListener {
private val kTag = "SearchMarkerActivity"
private val context = this
@@ -76,38 +66,10 @@
private var signalEnergy = 0 //标识器信号强度
private var gravity: FloatArray? = null
private var geomagnetic: FloatArray? = null
- private var serialPortService: SerialPortService? = null
- private lateinit var searchSignalEnergyTimer: Timer
-
- private val serviceConnection = object : ServiceConnection {
- override fun onServiceConnected(name: ComponentName?, iBinder: IBinder?) {
- if (name != null && iBinder != null && iBinder is SerialPortService.ServiceBinder) {
- try {
- serialPortService = iBinder.getSerialPortService()
- Log.d(kTag, "onServiceConnected: 服务已绑定,开始搜索标识器")
- searchMarker()
- } catch (e: Exception) {
- Log.e(kTag, "onServiceConnected: 绑定服务时发生异常", e)
- }
- } else {
- Log.w(kTag, "onServiceConnected: name 或 iBinder 为 null")
- }
- }
-
- override fun onServiceDisconnected(name: ComponentName?) {
-
- }
- }
-
- companion object {
- var weakReferenceHandler: WeakReferenceHandler? = null
- }
override fun initOnCreate(savedInstanceState: Bundle?) {
- weakReferenceHandler = WeakReferenceHandler(this)
-
- val flag = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY) as String
- isExecuteTask = flag != "0"
+ val taskState = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY) as String
+ isExecuteTask = taskState != "0"
slowSoundResourceId = soundPool.load(this, R.raw.ring4, 1)
fastSoundResourceId = soundPool.load(this, R.raw.ring2, 1)
@@ -131,14 +93,11 @@
binding.taskStateView.isSelected = true
}
- //绑定串口通信服务
- Intent(this, SerialPortService::class.java).also {
- bindService(it, serviceConnection, Context.BIND_AUTO_CREATE)
- }
+ openSerialPort()
+ searchMarker(CurrentSegment.SearchMarker)
//在标识器信号强度很强的时候,从数据库中计算出距离最近的点,以防出现探测不到ID的情况
- searchSignalEnergyTimer = Timer()
- searchSignalEnergyTimer.schedule(object : TimerTask() {
+ Timer().schedule(object : TimerTask() {
override fun run() {
if (signalEnergy <= 700) {//18°
runOnUiThread {
@@ -183,21 +142,8 @@
}, 0, 2000)
}
- private val countDownTimer = object : CountDownTimer(10 * 1000, 1000) {
- override fun onTick(millisUntilFinished: Long) {
-
- }
-
- override fun onFinish() {
- LoadingDialog.dismiss()
- "标识器深度探测超时,请移动位置重试".show(context)
- searchMarker()
- }
- }
-
override fun initEvent() {
binding.depthButton.setOnClickListener {
- soundPool.autoPause()
val result = DataBaseManager.get.queryMarkerById(markerId)
if (result.isNotEmpty()) {
val tag = when (result.first().markerType) {
@@ -208,18 +154,25 @@
}
if (tag == '1') {
"此标识器无法读取埋深!".show(this)
- searchMarker()
} else {
+ soundPool.autoPause()
LoadingDialog.show(this, "正在探测标识器埋深,请稍后...")
- countDownTimer.start()
// 发送读取标识器埋设深度指令
- RuntimeCache.currentSegment = CurrentSegment.DetectMarkerDepth
- serialPortService?.writeCommand(tag)
+ detectDepth(tag)
+ object : CountDownTimer(3 * 1000, 1000) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ LoadingDialog.dismiss()
+ updateSegment(CurrentSegment.SearchMarker)
+ }
+ }.start()
}
} else {
LoadingDialog.dismiss()
"标识器未安装,安装成功后才可读取埋深!".show(this)
- searchMarker()
}
}
@@ -236,13 +189,11 @@
}
}
- override fun handleMessage(msg: Message): Boolean {
- val buffer = msg.obj as ByteArray
- if (msg.what == LocaleConstant.DETECT_MARKER_DEPTH) {
- val tag = (buffer.first().toInt() and 0xFF).toString(16).uppercase()
- if (tag == "53") {
+ override fun onDataReceived(buffer: ByteArray, segment: CurrentSegment) {
+ if (segment == CurrentSegment.DetectDepth) {
+ val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase()
+ if (flag == "53" && buffer.size == 5) {
LoadingDialog.dismiss()
- countDownTimer.cancel()
try {
AlertMessageDialog.Builder().setContext(context)
.setTitle("温馨提示")
@@ -251,54 +202,32 @@
.setOnDialogButtonClickListener(object :
AlertMessageDialog.OnDialogButtonClickListener {
override fun onConfirmClick() {
- searchMarker()
+ updateSegment(CurrentSegment.SearchMarker)
}
}).build().show()
} catch (e: WindowManager.BadTokenException) {
e.printStackTrace()
- } catch (e: NumberFormatException) {
- e.printStackTrace()
}
}
- } else if (msg.what == LocaleConstant.SEARCH_MARKER) {
- try {
- // 读取到信号强度
- when ((buffer.first().toInt() and 0xFF).toString(16).uppercase()) {
- "4E" -> {
- val signalEnergy = buffer.toSignalStrength()
+ } else if (segment == CurrentSegment.SearchMarker) {
+ val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase()
+ if (flag == "30" && buffer.size == 10) {
+ handleMarker(buffer.toMarkerId())
+ } else if (flag == "4E" && buffer.size == 5) {
+ val signalEnergy = buffer.toSignalStrength()
- //声音
- updateSound(signalEnergy)
+ //声音
+ updateSound(signalEnergy)
- //信号强度显示
- updateProgressBar(signalEnergy)
+ //信号强度显示
+ updateProgressBar(signalEnergy)
- //搜索信号文字显示
- updateTextResult(signalEnergy)
- }
-
- "30" -> {
- handleMarker(buffer.toMarkerId())
- }
-
- else -> {
- Log.d(kTag, "乱码数据: ${buffer.contentToString()}")
- }
- }
- } catch (e: Exception) {
- e.printStackTrace()
- Log.e(kTag, "Error processing buffer data", e)
+ //搜索信号文字显示
+ updateTextResult(signalEnergy)
+ } else {
+ Log.d(kTag, "乱码数据: ${buffer.contentToString()}")
}
}
- return true
- }
-
- /**
- * 搜索标识器
- * */
- private fun searchMarker() {
- RuntimeCache.currentSegment = CurrentSegment.SearchMarker
- serialPortService?.writeCommand('2', '6')
}
private fun updateSound(signalEnergy: Int) {
@@ -492,9 +421,8 @@
override fun onDestroy() {
super.onDestroy()
+ closeSerialPort()
soundPool.autoPause()
- RuntimeCache.currentSegment = null
locationKit.stopLocation()
- unbindService(serviceConnection)
}
}
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index c9b11ec..1a81160 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -77,7 +77,7 @@
dependencies {
//基础依赖库
- implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1'
+ implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.3'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
//Google官方授权框架
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2f152d8..5c645f0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -91,7 +91,6 @@
android:resource="@xml/file_paths" />
-
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
index 6cb496c..e5fe1f5 100644
--- a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
@@ -1,6 +1,7 @@
package com.casic.common.detector.gd.base
import android.app.Application
+import android.util.Log
import com.casic.common.detector.gd.greendao.DaoMaster
import com.casic.common.detector.gd.greendao.DaoSession
import com.casic.common.detector.gd.uart.SerialPort
@@ -52,6 +53,7 @@
//千寻报文数据下发串口号
add(SerialPort(File("/dev/ttyS1"), 9600, 0))
}
+ Log.d(kTag, "onCreate: 已初始化 ${serialPorts.size} 个串口")
} catch (e: SecurityException) {
"您没有串口的读写权限!".show(this)
} catch (e: IOException) {
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
new file mode 100644
index 0000000..08b3e19
--- /dev/null
+++ b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
@@ -0,0 +1,204 @@
+package com.casic.common.detector.gd.base
+
+import android.os.Bundle
+import android.os.Handler
+import android.os.Message
+import android.util.Log
+import androidx.appcompat.app.AppCompatActivity
+import androidx.viewbinding.ViewBinding
+import com.casic.common.detector.gd.utils.CurrentSegment
+import com.casic.common.detector.gd.utils.GpioManager
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import java.io.IOException
+import java.util.Timer
+import java.util.TimerTask
+import java.util.concurrent.atomic.AtomicInteger
+
+abstract class SerialPortActivity : AppCompatActivity(), Handler.Callback {
+
+ private val kTag = "SerialPortActivity"
+ private val taskTimer by lazy { Timer() }
+ private val weakReferenceHandler by lazy { WeakReferenceHandler(this) }
+
+ //输出流
+ private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
+
+ //输入流
+ private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
+ private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
+
+ private var segment: CurrentSegment? = null
+
+ protected lateinit var binding: VB
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = initViewBinding()
+ setContentView(binding.root)
+ setupTopBarLayout()
+ initOnCreate(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = firstInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = lastInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+ }
+
+ /**
+ * 初始化ViewBinding
+ */
+ abstract fun initViewBinding(): VB
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initOnCreate(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ abstract fun onDataReceived(buffer: ByteArray, segment: CurrentSegment)
+
+ override fun handleMessage(msg: Message): Boolean {
+ if (msg.what == 2025012001) {
+ val bytes = msg.obj as ByteArray
+ if (segment == null) {
+ return true
+ }
+ Log.d(kTag, "$segment - ${bytes.contentToString()}")
+ onDataReceived(bytes, segment!!)
+ }
+ return true
+ }
+
+ private var readMarkerIdTask: TimerTask? = null
+ private var searchMarkerTask: TimerTask? = null
+
+ fun readMarkerId() {
+ this.segment = CurrentSegment.InstallMarker
+ readMarkerIdTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(readMarkerIdTask, 0, 300)
+ }
+
+ fun detectDepth(tag: Char) {
+ this.segment = CurrentSegment.DetectDepth
+ outStream.write('3'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write(tag.code)
+ outStream.flush()
+ }
+
+ fun updateSegment(segment: CurrentSegment) {
+ this.segment = segment
+ }
+
+ fun searchMarker(segment: CurrentSegment) {
+ this.segment = segment
+ searchMarkerTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write('6'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(searchMarkerTask, 0, 300)
+ }
+
+ /***************************************************************************************/
+ private val gpioManager by lazy { GpioManager() }
+
+ /**
+ * 读取数据 1
+ * 暂停读取 0
+ * */
+ private val gpioState = AtomicInteger(0)
+ fun openSerialPort() {
+ if (gpioState.get() != 1) {
+ gpioManager.setGpioHigh("18")
+ gpioState.set(1)
+ Log.d(kTag, "openSerialPort: 调高串口电位")
+ } else {
+ Log.d(kTag, "openSerialPort: 已经是高电位,直接读数据")
+ }
+ }
+
+ fun closeSerialPort() {
+ if (segment != null) {
+ segment = null
+ }
+ readMarkerIdTask?.cancel()
+ searchMarkerTask?.cancel()
+ if (gpioState.get() == 0) {
+ Log.d(kTag, "closeSerialPort: 已经是低电位,不响应")
+ return
+ }
+ // 降低串口电位
+ gpioManager.setGpioLow("18")
+ gpioState.set(0)
+ Log.d(kTag, "closeSerialPort: 降低串口电位")
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ closeSerialPort()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
index 442189e..5c3ee01 100644
--- a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
@@ -1,42 +1,20 @@
package com.casic.common.detector.gd.extensions
-import android.util.Log
-
/**
* 因为数据频率很高,而且每一帧数据至少有一个信号值,如果有多个信号强度值,取平均值
*
* [78, 53, 49, 55, 51]
*
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
* */
fun ByteArray.toSignalStrength(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var strength = 0
+ for (byte in dataBytes) {
+ strength = strength * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return strength
}
/**
@@ -44,32 +22,13 @@
*
* [48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
*
- * [48, 48, 48, 56, 56, 57, 49, 48, 55, 51, 48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
- *
* */
fun ByteArray.toMarkerId(): String {
- //判断数据合理性
- val validBytes = if (this.size % 10 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 10) * 10
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ val id = this.map { it.toInt().toChar() }.joinToString("")
+ if (id.matches("-?\\d+".toRegex())) {
+ return id
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 10) {
- // 每10个字节取一次数据转为ASCII
- val tempBytes = validBytes.sliceArray(i until minOf(i + 10, validBytes.size))
- val string = tempBytes.map { it.toInt().toChar() }.joinToString("")
- if (string.matches("-?\\d+".toRegex())) {
- list.add(string)
- } else {
- Log.d("kTag", "toDeviceCode: 编号解析失败")
- }
- }
- return list.last()
+ return ""
}
/**
@@ -77,31 +36,14 @@
*
* [83, 48, 48, 48, 57]
*
- * [83, 48, 48, 48, 57, 83, 48, 48, 48, 57]
* */
fun ByteArray.toBuryDepth(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var depth = 0
+ for (byte in dataBytes) {
+ depth = depth * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return depth
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt b/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
deleted file mode 100644
index 76cf583..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
+++ /dev/null
@@ -1,136 +0,0 @@
-package com.casic.common.detector.gd.service
-
-import android.app.Service
-import android.content.Intent
-import android.os.Binder
-import android.os.IBinder
-import android.util.Log
-import com.casic.common.detector.gd.base.BaseApplication
-import com.casic.common.detector.gd.utils.CurrentSegment
-import com.casic.common.detector.gd.utils.LocaleConstant
-import com.casic.common.detector.gd.utils.RuntimeCache
-import com.casic.common.detector.gd.view.InstallMarkerActivity
-import com.casic.common.detector.gd.view.MainActivity
-import com.casic.common.detector.gd.view.SearchMarkerActivity
-import java.io.IOException
-import java.io.InputStream
-import java.util.concurrent.Executors
-import java.util.concurrent.TimeUnit
-
-class SerialPortService : Service() {
-
- private val kTag = "SerialPortService"
- private val sendExecutor = Executors.newFixedThreadPool(5)
- private val readExecutor = Executors.newSingleThreadScheduledExecutor()
-
- //输出流
- private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
-
- //输入流
- private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
- private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
-
- override fun onCreate() {
- super.onCreate()
- try {
- // 使用单线程调度器读取数据
- readExecutor.scheduleAtFixedRate({
- readData(firstInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
-
- readExecutor.scheduleAtFixedRate({
- readData(lastInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- private fun readData(inputStream: InputStream) {
- try {
- val buffer = ByteArray(1024)
- var bytesRead: Int
- while (inputStream.available() > 0) {
- bytesRead = inputStream.read(buffer)
- if (bytesRead > 0) {
- when (RuntimeCache.currentSegment) {
- CurrentSegment.DetectMarkerDepth -> {
- //深度
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.DETECT_MARKER_DEPTH
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.InstallMarker -> {
- //安装点
- InstallMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.INSTALL_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.FreeInspection -> {
- //自由巡检
- MainActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.FREE_INSPECTION
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.SearchMarker -> {
- //搜索标识器
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.SEARCH_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- else -> {
- val bytes = buffer.copyOf(bytesRead)
- Log.d(kTag, "空状态,不处理 ===> ${bytes.contentToString()}")
- }
- }
- }
- }
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- fun writeCommand(vararg command: Char) {
- Log.d(kTag, "writeCommand: ${command.contentToString()}")
- if (command.size == 1) {
- sendExecutor.submit {
- outStream.write(command.first().code)
- outStream.flush()
- }
- } else {
- command.forEach {
- sendExecutor.submit {
- outStream.write(it.code)
- outStream.flush()
- }
- Thread.sleep(1000)
- }
- }
- }
-
- override fun onBind(intent: Intent?): IBinder {
- return ServiceBinder()
- }
-
- inner class ServiceBinder : Binder() {
- fun getSerialPortService(): SerialPortService {
- return this@SerialPortService
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt b/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
index 0606b72..9efa097 100644
--- a/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
@@ -1,23 +1,23 @@
package com.casic.common.detector.gd.utils
-sealed class CurrentSegment {
+enum class CurrentSegment {
/**
* 安装标识器
* */
- object InstallMarker : CurrentSegment()
+ InstallMarker,
/**
* 自由巡检
* */
- object FreeInspection : CurrentSegment()
+ FreeInspection,
/**
* 搜索标识器
* */
- object SearchMarker : CurrentSegment()
+ SearchMarker,
/**
* 探测标识器深度
* */
- object DetectMarkerDepth : CurrentSegment()
+ DetectDepth
}
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt
deleted file mode 100644
index c9151a8..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt
+++ /dev/null
@@ -1,150 +0,0 @@
-package com.casic.common.detector.gd.utils
-
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.SupervisorJob
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import okhttp3.Call
-import okhttp3.Callback
-import okhttp3.OkHttpClient
-import okhttp3.Request
-import okhttp3.Response
-import java.io.File
-import java.io.IOException
-import java.util.concurrent.atomic.AtomicBoolean
-
-class FileDownloadManager(builder: Builder) {
-
- private val httpClient by lazy { OkHttpClient() }
-
- class Builder {
- lateinit var url: String
- lateinit var suffix: String
- lateinit var directory: File
- lateinit var downloadListener: OnFileDownloadListener
-
- /**
- * 文件下载地址
- * */
- fun setDownloadFileSource(url: String): Builder {
- this.url = url
- return this
- }
-
- /**
- * 文件后缀
- * 如:apk等
- * */
- fun setFileSuffix(suffix: String): Builder {
- this.suffix = if (suffix.contains(".")) {
- //去掉前缀的点
- suffix.drop(1)
- } else {
- suffix
- }
- return this
- }
-
- /**
- * 文件保存的地址
- * */
- fun setFileSaveDirectory(directory: File): Builder {
- this.directory = directory
- return this
- }
-
- /**
- * 设置文件下载回调监听
- * */
- fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder {
- this.downloadListener = downloadListener
- return this
- }
-
- fun build(): FileDownloadManager {
- if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) {
- throw IllegalStateException("All properties must be initialized before building.")
- }
- return FileDownloadManager(this)
- }
- }
-
- private val url = builder.url
- private val suffix = builder.suffix
- private val directory = builder.directory
- private val listener = builder.downloadListener
-
- /**
- * 开始下载
- * */
- fun start() {
- val job = SupervisorJob()
- val scope = CoroutineScope(Dispatchers.Main + job)
-
- val request = Request.Builder().get().url(url).build()
- val newCall = httpClient.newCall(request)
- val isExecuting = AtomicBoolean(false)
-
- /**
- * 如果已被加入下载队列,则取消之前的,重新下载
- */
- if (isExecuting.getAndSet(true)) {
- newCall.cancel()
- }
-
- //异步下载文件
- newCall.enqueue(object : Callback {
- override fun onFailure(call: Call, e: IOException) {
- scope.launch(Dispatchers.Main) {
- listener.onFailed(e)
- }
- }
-
- override fun onResponse(call: Call, response: Response) {
- scope.launch(Dispatchers.IO) {
- val body = response.body
- if (body == null) {
- listener.onFailed(IOException("Response body is null"))
- throw IOException("Response body is null")
- } else {
- val inputStream = body.byteStream()
- val fileSize = body.contentLength()
-
- if (fileSize <= 0) {
- throw IllegalArgumentException("Invalid file size")
- }
- listener.onDownloadStart(fileSize)
-
- val file = File(directory, "${System.currentTimeMillis()}.${suffix}")
- file.outputStream().use { fos ->
- val buffer = ByteArray(2048)
- var sum = 0L
- var read: Int
- while (inputStream.read(buffer).also { read = it } != -1) {
- fos.write(buffer, 0, read)
- sum += read.toLong()
- withContext(Dispatchers.Main) {
- listener.onProgressChanged(sum)
- }
- }
- }
-
- withContext(Dispatchers.Main) {
- listener.onDownloadEnd(file)
- }
-
- job.cancel()
- }
- }
- }
- })
- }
-
- interface OnFileDownloadListener {
- fun onDownloadStart(total: Long)
- fun onProgressChanged(progress: Long)
- fun onDownloadEnd(file: File)
- fun onFailed(t: Throwable)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt b/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
index 2334680..c658924 100644
--- a/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
@@ -14,10 +14,6 @@
const val PERMISSIONS_CODE = 999
const val MAX_DISTANCE = 5.5f //表盘最大显示距离
- const val FREE_INSPECTION = 20250101
- const val INSTALL_MARKER = 20250102
- const val DETECT_MARKER_DEPTH = 20250103
- const val SEARCH_MARKER = 20250104
const val AUTO_SAVE = "AUTO_SAVE"
const val USER_ACCOUNT = "USER_ACCOUNT"
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt b/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt
deleted file mode 100644
index 104f971..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.casic.common.detector.gd.utils
-
-object RuntimeCache {
- var currentSegment: CurrentSegment? = null
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt
index c5f18a6..b3dce3c 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt
@@ -1,26 +1,19 @@
package com.casic.common.detector.gd.view
import android.app.DatePickerDialog
-import android.content.ComponentName
-import android.content.Context
import android.content.DialogInterface
-import android.content.Intent
-import android.content.ServiceConnection
import android.hardware.Camera
import android.media.AudioAttributes
import android.media.SoundPool
import android.os.Bundle
import android.os.CountDownTimer
-import android.os.Handler
-import android.os.IBinder
-import android.os.Message
-import android.util.Log
import android.view.View
import android.widget.AdapterView
import androidx.lifecycle.ViewModelProvider
import com.amap.api.location.AMapLocation
import com.casic.common.detector.gd.R
import com.casic.common.detector.gd.adapter.EditableImageAdapter
+import com.casic.common.detector.gd.base.SerialPortActivity
import com.casic.common.detector.gd.bean.MarkerLocalBean
import com.casic.common.detector.gd.callback.OnGetLocationListener
import com.casic.common.detector.gd.callback.OnImageCompressListener
@@ -33,18 +26,15 @@
import com.casic.common.detector.gd.extensions.toColor
import com.casic.common.detector.gd.extensions.toMarkerId
import com.casic.common.detector.gd.extensions.toObjectType
-import com.casic.common.detector.gd.service.SerialPortService
import com.casic.common.detector.gd.utils.CurrentSegment
import com.casic.common.detector.gd.utils.DataBaseManager
import com.casic.common.detector.gd.utils.LocaleConstant
import com.casic.common.detector.gd.utils.LocationKit
-import com.casic.common.detector.gd.utils.RuntimeCache
import com.casic.common.detector.gd.vm.TaskViewModel
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.appendZero
import com.pengxh.kt.lite.extensions.dateToTimestamp
import com.pengxh.kt.lite.extensions.navigatePageTo
@@ -55,13 +45,12 @@
import com.pengxh.kt.lite.utils.LoadState
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.utils.SaveKeyValues
-import com.pengxh.kt.lite.utils.WeakReferenceHandler
import com.pengxh.kt.lite.widget.TitleBarView
import java.io.File
import java.util.Calendar
import java.util.Date
-class InstallMarkerActivity : KotlinBaseActivity(), Handler.Callback {
+class InstallMarkerActivity : SerialPortActivity() {
private val kTag = "InstallMarkerActivity"
private val context = this
@@ -73,7 +62,6 @@
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build()
private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build()
private var soundResourceId = 0
- private var serialPortService: SerialPortService? = null
private lateinit var imageAdapter: EditableImageAdapter
override fun initEvent() {
@@ -255,18 +243,18 @@
//读标识器
binding.readMarkerButton.setOnClickListener {
+ openSerialPort()
LoadingDialog.show(this, "标识器读取中,请稍后...")
countDownTimer.start()
binding.readMarkerButton.isEnabled = false
- RuntimeCache.currentSegment = CurrentSegment.InstallMarker
- serialPortService?.writeCommand('2')
+ readMarkerId()
}
}
- override fun handleMessage(msg: Message): Boolean {
- if (msg.what == LocaleConstant.INSTALL_MARKER) {
- val buffer = msg.obj as ByteArray
- if ((buffer.first().toInt() and 0xFF).toString(16).uppercase() == "30") {
+ override fun onDataReceived(buffer: ByteArray, segment: CurrentSegment) {
+ if (segment == CurrentSegment.InstallMarker) {
+ val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase()
+ if (flag == "30" && buffer.size == 10) {
val markerId = buffer.toMarkerId()
LoadingDialog.dismiss()
countDownTimer.cancel()
@@ -274,7 +262,6 @@
binding.identifierInclude.identifierIdView.text = markerId
}
}
- return true
}
/**
@@ -363,37 +350,7 @@
})
}
- private val serviceConnection = object : ServiceConnection {
- override fun onServiceConnected(name: ComponentName?, iBinder: IBinder?) {
- if (name != null && iBinder != null && iBinder is SerialPortService.ServiceBinder) {
- try {
- serialPortService = iBinder.getSerialPortService()
- Log.d(kTag, "onServiceConnected: 服务已绑定")
- } catch (e: Exception) {
- Log.e(kTag, "onServiceConnected: 绑定服务时发生异常", e)
- }
- } else {
- Log.w(kTag, "onServiceConnected: name 或 iBinder 为 null")
- }
- }
-
- override fun onServiceDisconnected(name: ComponentName?) {
- //在连接正常关闭的情况下不会被调用, 只在Service被破坏了或者被杀死的时候调用
- }
- }
-
- companion object {
- var weakReferenceHandler: WeakReferenceHandler? = null
- }
-
override fun initOnCreate(savedInstanceState: Bundle?) {
- weakReferenceHandler = WeakReferenceHandler(this)
-
- //绑定串口通信服务
- Intent(this, SerialPortService::class.java).also {
- bindService(it, serviceConnection, Context.BIND_AUTO_CREATE)
- }
-
locationKit.getCurrentLocation(true, object : OnGetLocationListener {
override fun onSuccess(location: AMapLocation) {
binding.identifierInclude.lngView.text = location.longitude.toString()
@@ -552,8 +509,6 @@
override fun onDestroy() {
super.onDestroy()
- RuntimeCache.currentSegment = null
locationKit.stopLocation()
- unbindService(serviceConnection)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt
index 8a798b6..2c48cc9 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt
@@ -1,18 +1,12 @@
package com.casic.common.detector.gd.view
import android.app.Activity
-import android.content.ComponentName
-import android.content.Context
import android.content.Intent
-import android.content.ServiceConnection
import android.graphics.BitmapFactory
import android.graphics.Color
import android.media.AudioAttributes
import android.media.SoundPool
import android.os.Bundle
-import android.os.Handler
-import android.os.IBinder
-import android.os.Message
import android.util.Log
import android.view.KeyEvent
import android.view.View
@@ -34,6 +28,7 @@
import com.amap.api.maps.model.MyLocationStyle
import com.casic.common.detector.gd.R
import com.casic.common.detector.gd.base.BaseApplication
+import com.casic.common.detector.gd.base.SerialPortActivity
import com.casic.common.detector.gd.bean.MarkerLocalBean
import com.casic.common.detector.gd.bean.TaskLocalBean
import com.casic.common.detector.gd.callback.OnGetAddressListener
@@ -47,32 +42,27 @@
import com.casic.common.detector.gd.model.TaskDetailLocalModel
import com.casic.common.detector.gd.model.TaskModel
import com.casic.common.detector.gd.service.NtripConnectService
-import com.casic.common.detector.gd.service.SerialPortService
import com.casic.common.detector.gd.utils.CurrentSegment
import com.casic.common.detector.gd.utils.DataBaseManager
import com.casic.common.detector.gd.utils.ExcelKit
-import com.casic.common.detector.gd.utils.FileDownloadManager
import com.casic.common.detector.gd.utils.FileType
-import com.casic.common.detector.gd.utils.GpioManager
import com.casic.common.detector.gd.utils.LocaleConstant
import com.casic.common.detector.gd.utils.LocationKit
import com.casic.common.detector.gd.utils.RouteOnMap
-import com.casic.common.detector.gd.utils.RuntimeCache
import com.casic.common.detector.gd.vm.TaskViewModel
import com.casic.common.detector.gd.widgets.MarkerDetailDialog
import com.casic.common.detector.gd.widgets.QueryMarkerDialog
import com.casic.common.detector.gd.widgets.SamplePopupWindow
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.createDownloadFileDir
import com.pengxh.kt.lite.extensions.dp2px
import com.pengxh.kt.lite.extensions.isNetworkConnected
import com.pengxh.kt.lite.extensions.navigatePageTo
import com.pengxh.kt.lite.extensions.show
import com.pengxh.kt.lite.extensions.timestampToCompleteDate
+import com.pengxh.kt.lite.utils.FileDownloadManager
import com.pengxh.kt.lite.utils.LoadState
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.utils.SaveKeyValues
-import com.pengxh.kt.lite.utils.WeakReferenceHandler
import com.pengxh.kt.lite.widget.TitleBarView
import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
import com.pengxh.kt.lite.widget.dialog.AlertInputDialog
@@ -82,45 +72,13 @@
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
-import java.util.concurrent.atomic.AtomicInteger
-class MainActivity : KotlinBaseActivity(), AMap.OnMarkerClickListener,
- OnMapLongClickListener, Handler.Callback {
+class MainActivity : SerialPortActivity(), AMap.OnMarkerClickListener,
+ OnMapLongClickListener {
private val kTag = "MainActivity"
private val context = this
-
- /***************************************************************************************/
- private val gpioManager by lazy { GpioManager() }
-
- /**
- * 读取数据 1
- * 暂停读取 0
- * */
- private val gpioState = AtomicInteger(0)
- private fun openSerialPort() {
- if (gpioState.get() != 1) {
- gpioManager.setGpioHigh("18")
- gpioState.set(1)
- Log.d(kTag, "openSerialPort: 调高串口电位")
- } else {
- Log.d(kTag, "openSerialPort: 已经是高电位,直接读数据")
- }
- }
-
- private fun closeSerialPort() {
- if (gpioState.get() == 0) {
- Log.d(kTag, "closeSerialPort: 已经是低电位,直接返回")
- return
- }
- // 降低串口电位
- gpioManager.setGpioLow("18")
- gpioState.set(0)
- Log.d(kTag, "closeSerialPort: 降低串口电位")
- }
-
- /***************************************************************************************/
private val samplePopupWindow by lazy { SamplePopupWindow(this) }
private val detailDialog by lazy { MarkerDetailDialog(this) }
private val locationKit by lazy { LocationKit(this) }
@@ -133,7 +91,6 @@
private var freeTaskTitle = ""
private var ids = HashSet()
private var freeTaskId: String? = null
- private var serialPortService: SerialPortService? = null
private var soundResourceId = 0
private var isExecuteTask = false
private lateinit var aMap: AMap
@@ -146,43 +103,13 @@
binding.rootView.initImmersionBar(this, false, R.color.themeColor)
}
- private val serviceConnection = object : ServiceConnection {
- override fun onServiceConnected(name: ComponentName?, iBinder: IBinder?) {
- if (name != null && iBinder != null && iBinder is SerialPortService.ServiceBinder) {
- try {
- serialPortService = iBinder.getSerialPortService()
- Log.d(kTag, "onServiceConnected: 服务已绑定")
- openSerialPort()
- } catch (e: Exception) {
- Log.e(kTag, "onServiceConnected: 绑定服务时发生异常", e)
- }
- } else {
- Log.w(kTag, "onServiceConnected: name 或 iBinder 为 null")
- }
- }
-
- override fun onServiceDisconnected(name: ComponentName?) {
-
- }
- }
-
- companion object {
- var weakReferenceHandler: WeakReferenceHandler? = null
- }
-
override fun initOnCreate(savedInstanceState: Bundle?) {
- weakReferenceHandler = WeakReferenceHandler(this)
-
//地图初始化
initMapConfig(savedInstanceState)
- //绑定串口通信服务
- Intent(this, SerialPortService::class.java).also {
- bindService(it, serviceConnection, Context.BIND_AUTO_CREATE)
- }
- Intent(this, NtripConnectService::class.java).also {
- startService(it)
- }
+// Intent(this, NtripConnectService::class.java).also {
+// startService(it)
+// }
soundResourceId = soundPool.load(this, R.raw.ring3, 1)
//右上角菜单
@@ -211,7 +138,7 @@
showMarkersOnMap()
}
- override fun onFailed(t: Throwable) {
+ override fun onDownloadFailed(t: Throwable) {
t.printStackTrace()
}
@@ -446,7 +373,7 @@
override fun onConfirmClick() {
isFreeTask = false
soundPool.autoPause()
- RuntimeCache.currentSegment = null
+ closeSerialPort()
binding.stopFreeTaskButton.visibility = View.GONE
if (freeTaskId.isNullOrBlank()) {
@@ -499,11 +426,7 @@
} else {
"此工单下无标识器,将执行自由巡检任务".show(context)
freeTaskId = task.taskId
-
- binding.stopFreeTaskButton.visibility = View.VISIBLE
- isFreeTask = true
- RuntimeCache.currentSegment = CurrentSegment.FreeInspection
- serialPortService?.writeCommand('2', '6')
+ detectMarker()
}
}
@@ -524,21 +447,22 @@
freeTaskTitle = value
val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String
taskViewModel.createFreeTask(context, userId, value)
-
- binding.stopFreeTaskButton.visibility = View.VISIBLE
- isFreeTask = true
- RuntimeCache.currentSegment = CurrentSegment.FreeInspection
- serialPortService?.writeCommand('2', '6')
+ detectMarker()
}
override fun onCancelClick() {}
}).build().show()
}
- override fun handleMessage(msg: Message): Boolean {
- if (msg.what == LocaleConstant.FREE_INSPECTION) {
- val buffer = msg.obj as ByteArray
- //只响一次,因为探测频率高,所以依旧是连续的报警声
+ private fun detectMarker() {
+ binding.stopFreeTaskButton.visibility = View.VISIBLE
+ isFreeTask = true
+ openSerialPort()
+ searchMarker(CurrentSegment.FreeInspection)
+ }
+
+ override fun onDataReceived(buffer: ByteArray, segment: CurrentSegment) {
+ if (segment == CurrentSegment.FreeInspection) {
soundPool.play(soundResourceId, 1f, 1f, 0, 0, 1f)
when ((buffer.first().toInt() and 0xFF).toString(16).uppercase()) {
"4E" -> {
@@ -552,27 +476,30 @@
val markerId = buffer.toMarkerId()
//添加地图Marker
if (!ids.contains(markerId)) {
- //根据markerId查询标识器经纬度
- val labels = DataBaseManager.get.queryMarkerById(markerId)
- if (labels.isNotEmpty()) {
- val bean = labels.first()
- aMap.addMarker(
- MarkerOptions()
- .position(LatLng(bean.lat.toDouble(), bean.lng.toDouble()))
- .icon(BitmapDescriptorFactory.fromResource(R.mipmap.label_blue1))
+ val markers = DataBaseManager.get.queryMarkerById(markerId)
+ if (markers.isNotEmpty()) {
+ val marker = markers.first()
+ val latLng = LatLng(
+ marker.lat.toDouble(), marker.lng.toDouble()
)
+ val resource = BitmapDescriptorFactory.fromResource(
+ R.mipmap.label_blue1
+ )
+ val options = MarkerOptions().position(latLng).icon(resource)
+ aMap.addMarker(options)
}
}
ids.add(markerId)
//显示标识器详细信息
if (!detailDialog.isShowing) {
- val markerBean = DataBaseManager.get.queryMarkerById(markerId).firstOrNull()
- if (markerBean == null) {
- "无法查询到此ID【${markerId}】的信息".show(context)
- } else {
- detailDialog.setMarker(markerBean)
- detailDialog.show()
+ DataBaseManager.get.queryMarkerById(markerId).firstOrNull().apply {
+ if (this == null) {
+ "无法查询到此ID【${markerId}】的信息".show(context)
+ } else {
+ detailDialog.setMarker(this)
+ detailDialog.show()
+ }
}
}
}
@@ -582,7 +509,6 @@
}
}
}
- return true
}
override fun observeRequestState() {
@@ -865,9 +791,6 @@
override fun onResume() {
super.onResume()
binding.mapView.onResume()
- if (serialPortService != null) {
- openSerialPort()
- }
}
override fun onPause() {
@@ -885,8 +808,6 @@
binding.mapView.onDestroy()
soundPool.autoPause()
locationKit.stopLocation()
- unbindService(serviceConnection)
- closeSerialPort()
BaseApplication.get().closeSerialPort()
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/SatelliteStatusActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/SatelliteStatusActivity.kt
index 9f2d5cd..0f1611d 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/SatelliteStatusActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/SatelliteStatusActivity.kt
@@ -74,7 +74,7 @@
locationManager.registerGnssStatusCallback(gnssStatusListener, null)
satelliteAdapter = SatelliteRecyclerAdapter(this, satelliteCollection)
binding.recyclerView.adapter = satelliteAdapter
- binding.recyclerView.addItemDecoration(RecyclerViewItemDivider(1, Color.WHITE))
+ binding.recyclerView.addItemDecoration(RecyclerViewItemDivider(0f, 0f, Color.WHITE))
//高德定位
locationKit.getCurrentLocation(false, object : OnGetLocationListener {
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt
index c7c8bb9..5417e1f 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt
@@ -1,9 +1,5 @@
package com.casic.common.detector.gd.view
-import android.content.ComponentName
-import android.content.Context
-import android.content.Intent
-import android.content.ServiceConnection
import android.graphics.Color
import android.hardware.Sensor
import android.hardware.SensorEvent
@@ -13,9 +9,6 @@
import android.media.SoundPool
import android.os.Bundle
import android.os.CountDownTimer
-import android.os.Handler
-import android.os.IBinder
-import android.os.Message
import android.util.Log
import android.view.View
import android.view.WindowManager
@@ -25,28 +18,25 @@
import com.amap.api.maps.AMapUtils
import com.amap.api.maps.model.LatLng
import com.casic.common.detector.gd.R
+import com.casic.common.detector.gd.base.SerialPortActivity
import com.casic.common.detector.gd.callback.OnGetLocationListener
import com.casic.common.detector.gd.databinding.ActivitySearchMarkerBinding
import com.casic.common.detector.gd.extensions.toBuryDepth
import com.casic.common.detector.gd.extensions.toMarkerId
import com.casic.common.detector.gd.extensions.toSignalStrength
import com.casic.common.detector.gd.model.MarkerDistanceData
-import com.casic.common.detector.gd.service.SerialPortService
import com.casic.common.detector.gd.utils.CurrentSegment
import com.casic.common.detector.gd.utils.DataBaseManager
import com.casic.common.detector.gd.utils.LocaleConstant
import com.casic.common.detector.gd.utils.LocationKit
-import com.casic.common.detector.gd.utils.RuntimeCache
import com.casic.common.detector.gd.vm.TaskViewModel
import com.casic.common.detector.gd.widgets.RadarScanView
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.getSystemService
import com.pengxh.kt.lite.extensions.navigatePageTo
import com.pengxh.kt.lite.extensions.show
import com.pengxh.kt.lite.utils.LiteKitConstant
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.utils.SaveKeyValues
-import com.pengxh.kt.lite.utils.WeakReferenceHandler
import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -55,8 +45,8 @@
import java.util.TimerTask
import kotlin.math.atan2
-class SearchMarkerActivity : KotlinBaseActivity(),
- SensorEventListener, Handler.Callback {
+class SearchMarkerActivity : SerialPortActivity(),
+ SensorEventListener {
private val kTag = "SearchMarkerActivity"
private val context = this
@@ -76,38 +66,10 @@
private var signalEnergy = 0 //标识器信号强度
private var gravity: FloatArray? = null
private var geomagnetic: FloatArray? = null
- private var serialPortService: SerialPortService? = null
- private lateinit var searchSignalEnergyTimer: Timer
-
- private val serviceConnection = object : ServiceConnection {
- override fun onServiceConnected(name: ComponentName?, iBinder: IBinder?) {
- if (name != null && iBinder != null && iBinder is SerialPortService.ServiceBinder) {
- try {
- serialPortService = iBinder.getSerialPortService()
- Log.d(kTag, "onServiceConnected: 服务已绑定,开始搜索标识器")
- searchMarker()
- } catch (e: Exception) {
- Log.e(kTag, "onServiceConnected: 绑定服务时发生异常", e)
- }
- } else {
- Log.w(kTag, "onServiceConnected: name 或 iBinder 为 null")
- }
- }
-
- override fun onServiceDisconnected(name: ComponentName?) {
-
- }
- }
-
- companion object {
- var weakReferenceHandler: WeakReferenceHandler? = null
- }
override fun initOnCreate(savedInstanceState: Bundle?) {
- weakReferenceHandler = WeakReferenceHandler(this)
-
- val flag = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY) as String
- isExecuteTask = flag != "0"
+ val taskState = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY) as String
+ isExecuteTask = taskState != "0"
slowSoundResourceId = soundPool.load(this, R.raw.ring4, 1)
fastSoundResourceId = soundPool.load(this, R.raw.ring2, 1)
@@ -131,14 +93,11 @@
binding.taskStateView.isSelected = true
}
- //绑定串口通信服务
- Intent(this, SerialPortService::class.java).also {
- bindService(it, serviceConnection, Context.BIND_AUTO_CREATE)
- }
+ openSerialPort()
+ searchMarker(CurrentSegment.SearchMarker)
//在标识器信号强度很强的时候,从数据库中计算出距离最近的点,以防出现探测不到ID的情况
- searchSignalEnergyTimer = Timer()
- searchSignalEnergyTimer.schedule(object : TimerTask() {
+ Timer().schedule(object : TimerTask() {
override fun run() {
if (signalEnergy <= 700) {//18°
runOnUiThread {
@@ -183,21 +142,8 @@
}, 0, 2000)
}
- private val countDownTimer = object : CountDownTimer(10 * 1000, 1000) {
- override fun onTick(millisUntilFinished: Long) {
-
- }
-
- override fun onFinish() {
- LoadingDialog.dismiss()
- "标识器深度探测超时,请移动位置重试".show(context)
- searchMarker()
- }
- }
-
override fun initEvent() {
binding.depthButton.setOnClickListener {
- soundPool.autoPause()
val result = DataBaseManager.get.queryMarkerById(markerId)
if (result.isNotEmpty()) {
val tag = when (result.first().markerType) {
@@ -208,18 +154,25 @@
}
if (tag == '1') {
"此标识器无法读取埋深!".show(this)
- searchMarker()
} else {
+ soundPool.autoPause()
LoadingDialog.show(this, "正在探测标识器埋深,请稍后...")
- countDownTimer.start()
// 发送读取标识器埋设深度指令
- RuntimeCache.currentSegment = CurrentSegment.DetectMarkerDepth
- serialPortService?.writeCommand(tag)
+ detectDepth(tag)
+ object : CountDownTimer(3 * 1000, 1000) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ LoadingDialog.dismiss()
+ updateSegment(CurrentSegment.SearchMarker)
+ }
+ }.start()
}
} else {
LoadingDialog.dismiss()
"标识器未安装,安装成功后才可读取埋深!".show(this)
- searchMarker()
}
}
@@ -236,13 +189,11 @@
}
}
- override fun handleMessage(msg: Message): Boolean {
- val buffer = msg.obj as ByteArray
- if (msg.what == LocaleConstant.DETECT_MARKER_DEPTH) {
- val tag = (buffer.first().toInt() and 0xFF).toString(16).uppercase()
- if (tag == "53") {
+ override fun onDataReceived(buffer: ByteArray, segment: CurrentSegment) {
+ if (segment == CurrentSegment.DetectDepth) {
+ val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase()
+ if (flag == "53" && buffer.size == 5) {
LoadingDialog.dismiss()
- countDownTimer.cancel()
try {
AlertMessageDialog.Builder().setContext(context)
.setTitle("温馨提示")
@@ -251,54 +202,32 @@
.setOnDialogButtonClickListener(object :
AlertMessageDialog.OnDialogButtonClickListener {
override fun onConfirmClick() {
- searchMarker()
+ updateSegment(CurrentSegment.SearchMarker)
}
}).build().show()
} catch (e: WindowManager.BadTokenException) {
e.printStackTrace()
- } catch (e: NumberFormatException) {
- e.printStackTrace()
}
}
- } else if (msg.what == LocaleConstant.SEARCH_MARKER) {
- try {
- // 读取到信号强度
- when ((buffer.first().toInt() and 0xFF).toString(16).uppercase()) {
- "4E" -> {
- val signalEnergy = buffer.toSignalStrength()
+ } else if (segment == CurrentSegment.SearchMarker) {
+ val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase()
+ if (flag == "30" && buffer.size == 10) {
+ handleMarker(buffer.toMarkerId())
+ } else if (flag == "4E" && buffer.size == 5) {
+ val signalEnergy = buffer.toSignalStrength()
- //声音
- updateSound(signalEnergy)
+ //声音
+ updateSound(signalEnergy)
- //信号强度显示
- updateProgressBar(signalEnergy)
+ //信号强度显示
+ updateProgressBar(signalEnergy)
- //搜索信号文字显示
- updateTextResult(signalEnergy)
- }
-
- "30" -> {
- handleMarker(buffer.toMarkerId())
- }
-
- else -> {
- Log.d(kTag, "乱码数据: ${buffer.contentToString()}")
- }
- }
- } catch (e: Exception) {
- e.printStackTrace()
- Log.e(kTag, "Error processing buffer data", e)
+ //搜索信号文字显示
+ updateTextResult(signalEnergy)
+ } else {
+ Log.d(kTag, "乱码数据: ${buffer.contentToString()}")
}
}
- return true
- }
-
- /**
- * 搜索标识器
- * */
- private fun searchMarker() {
- RuntimeCache.currentSegment = CurrentSegment.SearchMarker
- serialPortService?.writeCommand('2', '6')
}
private fun updateSound(signalEnergy: Int) {
@@ -492,9 +421,8 @@
override fun onDestroy() {
super.onDestroy()
+ closeSerialPort()
soundPool.autoPause()
- RuntimeCache.currentSegment = null
locationKit.stopLocation()
- unbindService(serviceConnection)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/VersionControlActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/VersionControlActivity.kt
index ddc5a32..8641c79 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/VersionControlActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/VersionControlActivity.kt
@@ -13,17 +13,17 @@
import com.casic.common.detector.gd.databinding.ActivityVersionControlBinding
import com.casic.common.detector.gd.extensions.appendDownloadUrl
import com.casic.common.detector.gd.extensions.initImmersionBar
-import com.casic.common.detector.gd.utils.FileDownloadManager
import com.casic.common.detector.gd.utils.FileType
import com.casic.common.detector.gd.vm.VersionViewModel
-import com.casic.common.detector.gd.widgets.ProgressDialog
import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.createDownloadFileDir
import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.FileDownloadManager
import com.pengxh.kt.lite.utils.LoadState
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.widget.TitleBarView
import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.ProgressDialog
import java.io.File
class VersionControlActivity : KotlinBaseActivity() {
@@ -118,7 +118,7 @@
installApk(file)
}
- override fun onFailed(t: Throwable) {
+ override fun onDownloadFailed(t: Throwable) {
t.printStackTrace()
progressDialog.dismiss()
}
diff --git a/app/build.gradle b/app/build.gradle
index c9b11ec..1a81160 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -77,7 +77,7 @@
dependencies {
//基础依赖库
- implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1'
+ implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.3'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
//Google官方授权框架
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2f152d8..5c645f0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -91,7 +91,6 @@
android:resource="@xml/file_paths" />
-
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
index 6cb496c..e5fe1f5 100644
--- a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
@@ -1,6 +1,7 @@
package com.casic.common.detector.gd.base
import android.app.Application
+import android.util.Log
import com.casic.common.detector.gd.greendao.DaoMaster
import com.casic.common.detector.gd.greendao.DaoSession
import com.casic.common.detector.gd.uart.SerialPort
@@ -52,6 +53,7 @@
//千寻报文数据下发串口号
add(SerialPort(File("/dev/ttyS1"), 9600, 0))
}
+ Log.d(kTag, "onCreate: 已初始化 ${serialPorts.size} 个串口")
} catch (e: SecurityException) {
"您没有串口的读写权限!".show(this)
} catch (e: IOException) {
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
new file mode 100644
index 0000000..08b3e19
--- /dev/null
+++ b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
@@ -0,0 +1,204 @@
+package com.casic.common.detector.gd.base
+
+import android.os.Bundle
+import android.os.Handler
+import android.os.Message
+import android.util.Log
+import androidx.appcompat.app.AppCompatActivity
+import androidx.viewbinding.ViewBinding
+import com.casic.common.detector.gd.utils.CurrentSegment
+import com.casic.common.detector.gd.utils.GpioManager
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import java.io.IOException
+import java.util.Timer
+import java.util.TimerTask
+import java.util.concurrent.atomic.AtomicInteger
+
+abstract class SerialPortActivity : AppCompatActivity(), Handler.Callback {
+
+ private val kTag = "SerialPortActivity"
+ private val taskTimer by lazy { Timer() }
+ private val weakReferenceHandler by lazy { WeakReferenceHandler(this) }
+
+ //输出流
+ private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
+
+ //输入流
+ private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
+ private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
+
+ private var segment: CurrentSegment? = null
+
+ protected lateinit var binding: VB
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = initViewBinding()
+ setContentView(binding.root)
+ setupTopBarLayout()
+ initOnCreate(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = firstInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = lastInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+ }
+
+ /**
+ * 初始化ViewBinding
+ */
+ abstract fun initViewBinding(): VB
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initOnCreate(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ abstract fun onDataReceived(buffer: ByteArray, segment: CurrentSegment)
+
+ override fun handleMessage(msg: Message): Boolean {
+ if (msg.what == 2025012001) {
+ val bytes = msg.obj as ByteArray
+ if (segment == null) {
+ return true
+ }
+ Log.d(kTag, "$segment - ${bytes.contentToString()}")
+ onDataReceived(bytes, segment!!)
+ }
+ return true
+ }
+
+ private var readMarkerIdTask: TimerTask? = null
+ private var searchMarkerTask: TimerTask? = null
+
+ fun readMarkerId() {
+ this.segment = CurrentSegment.InstallMarker
+ readMarkerIdTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(readMarkerIdTask, 0, 300)
+ }
+
+ fun detectDepth(tag: Char) {
+ this.segment = CurrentSegment.DetectDepth
+ outStream.write('3'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write(tag.code)
+ outStream.flush()
+ }
+
+ fun updateSegment(segment: CurrentSegment) {
+ this.segment = segment
+ }
+
+ fun searchMarker(segment: CurrentSegment) {
+ this.segment = segment
+ searchMarkerTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write('6'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(searchMarkerTask, 0, 300)
+ }
+
+ /***************************************************************************************/
+ private val gpioManager by lazy { GpioManager() }
+
+ /**
+ * 读取数据 1
+ * 暂停读取 0
+ * */
+ private val gpioState = AtomicInteger(0)
+ fun openSerialPort() {
+ if (gpioState.get() != 1) {
+ gpioManager.setGpioHigh("18")
+ gpioState.set(1)
+ Log.d(kTag, "openSerialPort: 调高串口电位")
+ } else {
+ Log.d(kTag, "openSerialPort: 已经是高电位,直接读数据")
+ }
+ }
+
+ fun closeSerialPort() {
+ if (segment != null) {
+ segment = null
+ }
+ readMarkerIdTask?.cancel()
+ searchMarkerTask?.cancel()
+ if (gpioState.get() == 0) {
+ Log.d(kTag, "closeSerialPort: 已经是低电位,不响应")
+ return
+ }
+ // 降低串口电位
+ gpioManager.setGpioLow("18")
+ gpioState.set(0)
+ Log.d(kTag, "closeSerialPort: 降低串口电位")
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ closeSerialPort()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
index 442189e..5c3ee01 100644
--- a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
@@ -1,42 +1,20 @@
package com.casic.common.detector.gd.extensions
-import android.util.Log
-
/**
* 因为数据频率很高,而且每一帧数据至少有一个信号值,如果有多个信号强度值,取平均值
*
* [78, 53, 49, 55, 51]
*
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
* */
fun ByteArray.toSignalStrength(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var strength = 0
+ for (byte in dataBytes) {
+ strength = strength * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return strength
}
/**
@@ -44,32 +22,13 @@
*
* [48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
*
- * [48, 48, 48, 56, 56, 57, 49, 48, 55, 51, 48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
- *
* */
fun ByteArray.toMarkerId(): String {
- //判断数据合理性
- val validBytes = if (this.size % 10 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 10) * 10
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ val id = this.map { it.toInt().toChar() }.joinToString("")
+ if (id.matches("-?\\d+".toRegex())) {
+ return id
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 10) {
- // 每10个字节取一次数据转为ASCII
- val tempBytes = validBytes.sliceArray(i until minOf(i + 10, validBytes.size))
- val string = tempBytes.map { it.toInt().toChar() }.joinToString("")
- if (string.matches("-?\\d+".toRegex())) {
- list.add(string)
- } else {
- Log.d("kTag", "toDeviceCode: 编号解析失败")
- }
- }
- return list.last()
+ return ""
}
/**
@@ -77,31 +36,14 @@
*
* [83, 48, 48, 48, 57]
*
- * [83, 48, 48, 48, 57, 83, 48, 48, 48, 57]
* */
fun ByteArray.toBuryDepth(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var depth = 0
+ for (byte in dataBytes) {
+ depth = depth * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return depth
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt b/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
deleted file mode 100644
index 76cf583..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
+++ /dev/null
@@ -1,136 +0,0 @@
-package com.casic.common.detector.gd.service
-
-import android.app.Service
-import android.content.Intent
-import android.os.Binder
-import android.os.IBinder
-import android.util.Log
-import com.casic.common.detector.gd.base.BaseApplication
-import com.casic.common.detector.gd.utils.CurrentSegment
-import com.casic.common.detector.gd.utils.LocaleConstant
-import com.casic.common.detector.gd.utils.RuntimeCache
-import com.casic.common.detector.gd.view.InstallMarkerActivity
-import com.casic.common.detector.gd.view.MainActivity
-import com.casic.common.detector.gd.view.SearchMarkerActivity
-import java.io.IOException
-import java.io.InputStream
-import java.util.concurrent.Executors
-import java.util.concurrent.TimeUnit
-
-class SerialPortService : Service() {
-
- private val kTag = "SerialPortService"
- private val sendExecutor = Executors.newFixedThreadPool(5)
- private val readExecutor = Executors.newSingleThreadScheduledExecutor()
-
- //输出流
- private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
-
- //输入流
- private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
- private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
-
- override fun onCreate() {
- super.onCreate()
- try {
- // 使用单线程调度器读取数据
- readExecutor.scheduleAtFixedRate({
- readData(firstInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
-
- readExecutor.scheduleAtFixedRate({
- readData(lastInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- private fun readData(inputStream: InputStream) {
- try {
- val buffer = ByteArray(1024)
- var bytesRead: Int
- while (inputStream.available() > 0) {
- bytesRead = inputStream.read(buffer)
- if (bytesRead > 0) {
- when (RuntimeCache.currentSegment) {
- CurrentSegment.DetectMarkerDepth -> {
- //深度
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.DETECT_MARKER_DEPTH
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.InstallMarker -> {
- //安装点
- InstallMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.INSTALL_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.FreeInspection -> {
- //自由巡检
- MainActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.FREE_INSPECTION
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.SearchMarker -> {
- //搜索标识器
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.SEARCH_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- else -> {
- val bytes = buffer.copyOf(bytesRead)
- Log.d(kTag, "空状态,不处理 ===> ${bytes.contentToString()}")
- }
- }
- }
- }
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- fun writeCommand(vararg command: Char) {
- Log.d(kTag, "writeCommand: ${command.contentToString()}")
- if (command.size == 1) {
- sendExecutor.submit {
- outStream.write(command.first().code)
- outStream.flush()
- }
- } else {
- command.forEach {
- sendExecutor.submit {
- outStream.write(it.code)
- outStream.flush()
- }
- Thread.sleep(1000)
- }
- }
- }
-
- override fun onBind(intent: Intent?): IBinder {
- return ServiceBinder()
- }
-
- inner class ServiceBinder : Binder() {
- fun getSerialPortService(): SerialPortService {
- return this@SerialPortService
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt b/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
index 0606b72..9efa097 100644
--- a/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
@@ -1,23 +1,23 @@
package com.casic.common.detector.gd.utils
-sealed class CurrentSegment {
+enum class CurrentSegment {
/**
* 安装标识器
* */
- object InstallMarker : CurrentSegment()
+ InstallMarker,
/**
* 自由巡检
* */
- object FreeInspection : CurrentSegment()
+ FreeInspection,
/**
* 搜索标识器
* */
- object SearchMarker : CurrentSegment()
+ SearchMarker,
/**
* 探测标识器深度
* */
- object DetectMarkerDepth : CurrentSegment()
+ DetectDepth
}
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt
deleted file mode 100644
index c9151a8..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt
+++ /dev/null
@@ -1,150 +0,0 @@
-package com.casic.common.detector.gd.utils
-
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.SupervisorJob
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import okhttp3.Call
-import okhttp3.Callback
-import okhttp3.OkHttpClient
-import okhttp3.Request
-import okhttp3.Response
-import java.io.File
-import java.io.IOException
-import java.util.concurrent.atomic.AtomicBoolean
-
-class FileDownloadManager(builder: Builder) {
-
- private val httpClient by lazy { OkHttpClient() }
-
- class Builder {
- lateinit var url: String
- lateinit var suffix: String
- lateinit var directory: File
- lateinit var downloadListener: OnFileDownloadListener
-
- /**
- * 文件下载地址
- * */
- fun setDownloadFileSource(url: String): Builder {
- this.url = url
- return this
- }
-
- /**
- * 文件后缀
- * 如:apk等
- * */
- fun setFileSuffix(suffix: String): Builder {
- this.suffix = if (suffix.contains(".")) {
- //去掉前缀的点
- suffix.drop(1)
- } else {
- suffix
- }
- return this
- }
-
- /**
- * 文件保存的地址
- * */
- fun setFileSaveDirectory(directory: File): Builder {
- this.directory = directory
- return this
- }
-
- /**
- * 设置文件下载回调监听
- * */
- fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder {
- this.downloadListener = downloadListener
- return this
- }
-
- fun build(): FileDownloadManager {
- if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) {
- throw IllegalStateException("All properties must be initialized before building.")
- }
- return FileDownloadManager(this)
- }
- }
-
- private val url = builder.url
- private val suffix = builder.suffix
- private val directory = builder.directory
- private val listener = builder.downloadListener
-
- /**
- * 开始下载
- * */
- fun start() {
- val job = SupervisorJob()
- val scope = CoroutineScope(Dispatchers.Main + job)
-
- val request = Request.Builder().get().url(url).build()
- val newCall = httpClient.newCall(request)
- val isExecuting = AtomicBoolean(false)
-
- /**
- * 如果已被加入下载队列,则取消之前的,重新下载
- */
- if (isExecuting.getAndSet(true)) {
- newCall.cancel()
- }
-
- //异步下载文件
- newCall.enqueue(object : Callback {
- override fun onFailure(call: Call, e: IOException) {
- scope.launch(Dispatchers.Main) {
- listener.onFailed(e)
- }
- }
-
- override fun onResponse(call: Call, response: Response) {
- scope.launch(Dispatchers.IO) {
- val body = response.body
- if (body == null) {
- listener.onFailed(IOException("Response body is null"))
- throw IOException("Response body is null")
- } else {
- val inputStream = body.byteStream()
- val fileSize = body.contentLength()
-
- if (fileSize <= 0) {
- throw IllegalArgumentException("Invalid file size")
- }
- listener.onDownloadStart(fileSize)
-
- val file = File(directory, "${System.currentTimeMillis()}.${suffix}")
- file.outputStream().use { fos ->
- val buffer = ByteArray(2048)
- var sum = 0L
- var read: Int
- while (inputStream.read(buffer).also { read = it } != -1) {
- fos.write(buffer, 0, read)
- sum += read.toLong()
- withContext(Dispatchers.Main) {
- listener.onProgressChanged(sum)
- }
- }
- }
-
- withContext(Dispatchers.Main) {
- listener.onDownloadEnd(file)
- }
-
- job.cancel()
- }
- }
- }
- })
- }
-
- interface OnFileDownloadListener {
- fun onDownloadStart(total: Long)
- fun onProgressChanged(progress: Long)
- fun onDownloadEnd(file: File)
- fun onFailed(t: Throwable)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt b/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
index 2334680..c658924 100644
--- a/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
@@ -14,10 +14,6 @@
const val PERMISSIONS_CODE = 999
const val MAX_DISTANCE = 5.5f //表盘最大显示距离
- const val FREE_INSPECTION = 20250101
- const val INSTALL_MARKER = 20250102
- const val DETECT_MARKER_DEPTH = 20250103
- const val SEARCH_MARKER = 20250104
const val AUTO_SAVE = "AUTO_SAVE"
const val USER_ACCOUNT = "USER_ACCOUNT"
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt b/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt
deleted file mode 100644
index 104f971..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.casic.common.detector.gd.utils
-
-object RuntimeCache {
- var currentSegment: CurrentSegment? = null
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt
index c5f18a6..b3dce3c 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt
@@ -1,26 +1,19 @@
package com.casic.common.detector.gd.view
import android.app.DatePickerDialog
-import android.content.ComponentName
-import android.content.Context
import android.content.DialogInterface
-import android.content.Intent
-import android.content.ServiceConnection
import android.hardware.Camera
import android.media.AudioAttributes
import android.media.SoundPool
import android.os.Bundle
import android.os.CountDownTimer
-import android.os.Handler
-import android.os.IBinder
-import android.os.Message
-import android.util.Log
import android.view.View
import android.widget.AdapterView
import androidx.lifecycle.ViewModelProvider
import com.amap.api.location.AMapLocation
import com.casic.common.detector.gd.R
import com.casic.common.detector.gd.adapter.EditableImageAdapter
+import com.casic.common.detector.gd.base.SerialPortActivity
import com.casic.common.detector.gd.bean.MarkerLocalBean
import com.casic.common.detector.gd.callback.OnGetLocationListener
import com.casic.common.detector.gd.callback.OnImageCompressListener
@@ -33,18 +26,15 @@
import com.casic.common.detector.gd.extensions.toColor
import com.casic.common.detector.gd.extensions.toMarkerId
import com.casic.common.detector.gd.extensions.toObjectType
-import com.casic.common.detector.gd.service.SerialPortService
import com.casic.common.detector.gd.utils.CurrentSegment
import com.casic.common.detector.gd.utils.DataBaseManager
import com.casic.common.detector.gd.utils.LocaleConstant
import com.casic.common.detector.gd.utils.LocationKit
-import com.casic.common.detector.gd.utils.RuntimeCache
import com.casic.common.detector.gd.vm.TaskViewModel
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.appendZero
import com.pengxh.kt.lite.extensions.dateToTimestamp
import com.pengxh.kt.lite.extensions.navigatePageTo
@@ -55,13 +45,12 @@
import com.pengxh.kt.lite.utils.LoadState
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.utils.SaveKeyValues
-import com.pengxh.kt.lite.utils.WeakReferenceHandler
import com.pengxh.kt.lite.widget.TitleBarView
import java.io.File
import java.util.Calendar
import java.util.Date
-class InstallMarkerActivity : KotlinBaseActivity(), Handler.Callback {
+class InstallMarkerActivity : SerialPortActivity() {
private val kTag = "InstallMarkerActivity"
private val context = this
@@ -73,7 +62,6 @@
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build()
private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build()
private var soundResourceId = 0
- private var serialPortService: SerialPortService? = null
private lateinit var imageAdapter: EditableImageAdapter
override fun initEvent() {
@@ -255,18 +243,18 @@
//读标识器
binding.readMarkerButton.setOnClickListener {
+ openSerialPort()
LoadingDialog.show(this, "标识器读取中,请稍后...")
countDownTimer.start()
binding.readMarkerButton.isEnabled = false
- RuntimeCache.currentSegment = CurrentSegment.InstallMarker
- serialPortService?.writeCommand('2')
+ readMarkerId()
}
}
- override fun handleMessage(msg: Message): Boolean {
- if (msg.what == LocaleConstant.INSTALL_MARKER) {
- val buffer = msg.obj as ByteArray
- if ((buffer.first().toInt() and 0xFF).toString(16).uppercase() == "30") {
+ override fun onDataReceived(buffer: ByteArray, segment: CurrentSegment) {
+ if (segment == CurrentSegment.InstallMarker) {
+ val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase()
+ if (flag == "30" && buffer.size == 10) {
val markerId = buffer.toMarkerId()
LoadingDialog.dismiss()
countDownTimer.cancel()
@@ -274,7 +262,6 @@
binding.identifierInclude.identifierIdView.text = markerId
}
}
- return true
}
/**
@@ -363,37 +350,7 @@
})
}
- private val serviceConnection = object : ServiceConnection {
- override fun onServiceConnected(name: ComponentName?, iBinder: IBinder?) {
- if (name != null && iBinder != null && iBinder is SerialPortService.ServiceBinder) {
- try {
- serialPortService = iBinder.getSerialPortService()
- Log.d(kTag, "onServiceConnected: 服务已绑定")
- } catch (e: Exception) {
- Log.e(kTag, "onServiceConnected: 绑定服务时发生异常", e)
- }
- } else {
- Log.w(kTag, "onServiceConnected: name 或 iBinder 为 null")
- }
- }
-
- override fun onServiceDisconnected(name: ComponentName?) {
- //在连接正常关闭的情况下不会被调用, 只在Service被破坏了或者被杀死的时候调用
- }
- }
-
- companion object {
- var weakReferenceHandler: WeakReferenceHandler? = null
- }
-
override fun initOnCreate(savedInstanceState: Bundle?) {
- weakReferenceHandler = WeakReferenceHandler(this)
-
- //绑定串口通信服务
- Intent(this, SerialPortService::class.java).also {
- bindService(it, serviceConnection, Context.BIND_AUTO_CREATE)
- }
-
locationKit.getCurrentLocation(true, object : OnGetLocationListener {
override fun onSuccess(location: AMapLocation) {
binding.identifierInclude.lngView.text = location.longitude.toString()
@@ -552,8 +509,6 @@
override fun onDestroy() {
super.onDestroy()
- RuntimeCache.currentSegment = null
locationKit.stopLocation()
- unbindService(serviceConnection)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt
index 8a798b6..2c48cc9 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt
@@ -1,18 +1,12 @@
package com.casic.common.detector.gd.view
import android.app.Activity
-import android.content.ComponentName
-import android.content.Context
import android.content.Intent
-import android.content.ServiceConnection
import android.graphics.BitmapFactory
import android.graphics.Color
import android.media.AudioAttributes
import android.media.SoundPool
import android.os.Bundle
-import android.os.Handler
-import android.os.IBinder
-import android.os.Message
import android.util.Log
import android.view.KeyEvent
import android.view.View
@@ -34,6 +28,7 @@
import com.amap.api.maps.model.MyLocationStyle
import com.casic.common.detector.gd.R
import com.casic.common.detector.gd.base.BaseApplication
+import com.casic.common.detector.gd.base.SerialPortActivity
import com.casic.common.detector.gd.bean.MarkerLocalBean
import com.casic.common.detector.gd.bean.TaskLocalBean
import com.casic.common.detector.gd.callback.OnGetAddressListener
@@ -47,32 +42,27 @@
import com.casic.common.detector.gd.model.TaskDetailLocalModel
import com.casic.common.detector.gd.model.TaskModel
import com.casic.common.detector.gd.service.NtripConnectService
-import com.casic.common.detector.gd.service.SerialPortService
import com.casic.common.detector.gd.utils.CurrentSegment
import com.casic.common.detector.gd.utils.DataBaseManager
import com.casic.common.detector.gd.utils.ExcelKit
-import com.casic.common.detector.gd.utils.FileDownloadManager
import com.casic.common.detector.gd.utils.FileType
-import com.casic.common.detector.gd.utils.GpioManager
import com.casic.common.detector.gd.utils.LocaleConstant
import com.casic.common.detector.gd.utils.LocationKit
import com.casic.common.detector.gd.utils.RouteOnMap
-import com.casic.common.detector.gd.utils.RuntimeCache
import com.casic.common.detector.gd.vm.TaskViewModel
import com.casic.common.detector.gd.widgets.MarkerDetailDialog
import com.casic.common.detector.gd.widgets.QueryMarkerDialog
import com.casic.common.detector.gd.widgets.SamplePopupWindow
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.createDownloadFileDir
import com.pengxh.kt.lite.extensions.dp2px
import com.pengxh.kt.lite.extensions.isNetworkConnected
import com.pengxh.kt.lite.extensions.navigatePageTo
import com.pengxh.kt.lite.extensions.show
import com.pengxh.kt.lite.extensions.timestampToCompleteDate
+import com.pengxh.kt.lite.utils.FileDownloadManager
import com.pengxh.kt.lite.utils.LoadState
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.utils.SaveKeyValues
-import com.pengxh.kt.lite.utils.WeakReferenceHandler
import com.pengxh.kt.lite.widget.TitleBarView
import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
import com.pengxh.kt.lite.widget.dialog.AlertInputDialog
@@ -82,45 +72,13 @@
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
-import java.util.concurrent.atomic.AtomicInteger
-class MainActivity : KotlinBaseActivity(), AMap.OnMarkerClickListener,
- OnMapLongClickListener, Handler.Callback {
+class MainActivity : SerialPortActivity(), AMap.OnMarkerClickListener,
+ OnMapLongClickListener {
private val kTag = "MainActivity"
private val context = this
-
- /***************************************************************************************/
- private val gpioManager by lazy { GpioManager() }
-
- /**
- * 读取数据 1
- * 暂停读取 0
- * */
- private val gpioState = AtomicInteger(0)
- private fun openSerialPort() {
- if (gpioState.get() != 1) {
- gpioManager.setGpioHigh("18")
- gpioState.set(1)
- Log.d(kTag, "openSerialPort: 调高串口电位")
- } else {
- Log.d(kTag, "openSerialPort: 已经是高电位,直接读数据")
- }
- }
-
- private fun closeSerialPort() {
- if (gpioState.get() == 0) {
- Log.d(kTag, "closeSerialPort: 已经是低电位,直接返回")
- return
- }
- // 降低串口电位
- gpioManager.setGpioLow("18")
- gpioState.set(0)
- Log.d(kTag, "closeSerialPort: 降低串口电位")
- }
-
- /***************************************************************************************/
private val samplePopupWindow by lazy { SamplePopupWindow(this) }
private val detailDialog by lazy { MarkerDetailDialog(this) }
private val locationKit by lazy { LocationKit(this) }
@@ -133,7 +91,6 @@
private var freeTaskTitle = ""
private var ids = HashSet()
private var freeTaskId: String? = null
- private var serialPortService: SerialPortService? = null
private var soundResourceId = 0
private var isExecuteTask = false
private lateinit var aMap: AMap
@@ -146,43 +103,13 @@
binding.rootView.initImmersionBar(this, false, R.color.themeColor)
}
- private val serviceConnection = object : ServiceConnection {
- override fun onServiceConnected(name: ComponentName?, iBinder: IBinder?) {
- if (name != null && iBinder != null && iBinder is SerialPortService.ServiceBinder) {
- try {
- serialPortService = iBinder.getSerialPortService()
- Log.d(kTag, "onServiceConnected: 服务已绑定")
- openSerialPort()
- } catch (e: Exception) {
- Log.e(kTag, "onServiceConnected: 绑定服务时发生异常", e)
- }
- } else {
- Log.w(kTag, "onServiceConnected: name 或 iBinder 为 null")
- }
- }
-
- override fun onServiceDisconnected(name: ComponentName?) {
-
- }
- }
-
- companion object {
- var weakReferenceHandler: WeakReferenceHandler? = null
- }
-
override fun initOnCreate(savedInstanceState: Bundle?) {
- weakReferenceHandler = WeakReferenceHandler(this)
-
//地图初始化
initMapConfig(savedInstanceState)
- //绑定串口通信服务
- Intent(this, SerialPortService::class.java).also {
- bindService(it, serviceConnection, Context.BIND_AUTO_CREATE)
- }
- Intent(this, NtripConnectService::class.java).also {
- startService(it)
- }
+// Intent(this, NtripConnectService::class.java).also {
+// startService(it)
+// }
soundResourceId = soundPool.load(this, R.raw.ring3, 1)
//右上角菜单
@@ -211,7 +138,7 @@
showMarkersOnMap()
}
- override fun onFailed(t: Throwable) {
+ override fun onDownloadFailed(t: Throwable) {
t.printStackTrace()
}
@@ -446,7 +373,7 @@
override fun onConfirmClick() {
isFreeTask = false
soundPool.autoPause()
- RuntimeCache.currentSegment = null
+ closeSerialPort()
binding.stopFreeTaskButton.visibility = View.GONE
if (freeTaskId.isNullOrBlank()) {
@@ -499,11 +426,7 @@
} else {
"此工单下无标识器,将执行自由巡检任务".show(context)
freeTaskId = task.taskId
-
- binding.stopFreeTaskButton.visibility = View.VISIBLE
- isFreeTask = true
- RuntimeCache.currentSegment = CurrentSegment.FreeInspection
- serialPortService?.writeCommand('2', '6')
+ detectMarker()
}
}
@@ -524,21 +447,22 @@
freeTaskTitle = value
val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String
taskViewModel.createFreeTask(context, userId, value)
-
- binding.stopFreeTaskButton.visibility = View.VISIBLE
- isFreeTask = true
- RuntimeCache.currentSegment = CurrentSegment.FreeInspection
- serialPortService?.writeCommand('2', '6')
+ detectMarker()
}
override fun onCancelClick() {}
}).build().show()
}
- override fun handleMessage(msg: Message): Boolean {
- if (msg.what == LocaleConstant.FREE_INSPECTION) {
- val buffer = msg.obj as ByteArray
- //只响一次,因为探测频率高,所以依旧是连续的报警声
+ private fun detectMarker() {
+ binding.stopFreeTaskButton.visibility = View.VISIBLE
+ isFreeTask = true
+ openSerialPort()
+ searchMarker(CurrentSegment.FreeInspection)
+ }
+
+ override fun onDataReceived(buffer: ByteArray, segment: CurrentSegment) {
+ if (segment == CurrentSegment.FreeInspection) {
soundPool.play(soundResourceId, 1f, 1f, 0, 0, 1f)
when ((buffer.first().toInt() and 0xFF).toString(16).uppercase()) {
"4E" -> {
@@ -552,27 +476,30 @@
val markerId = buffer.toMarkerId()
//添加地图Marker
if (!ids.contains(markerId)) {
- //根据markerId查询标识器经纬度
- val labels = DataBaseManager.get.queryMarkerById(markerId)
- if (labels.isNotEmpty()) {
- val bean = labels.first()
- aMap.addMarker(
- MarkerOptions()
- .position(LatLng(bean.lat.toDouble(), bean.lng.toDouble()))
- .icon(BitmapDescriptorFactory.fromResource(R.mipmap.label_blue1))
+ val markers = DataBaseManager.get.queryMarkerById(markerId)
+ if (markers.isNotEmpty()) {
+ val marker = markers.first()
+ val latLng = LatLng(
+ marker.lat.toDouble(), marker.lng.toDouble()
)
+ val resource = BitmapDescriptorFactory.fromResource(
+ R.mipmap.label_blue1
+ )
+ val options = MarkerOptions().position(latLng).icon(resource)
+ aMap.addMarker(options)
}
}
ids.add(markerId)
//显示标识器详细信息
if (!detailDialog.isShowing) {
- val markerBean = DataBaseManager.get.queryMarkerById(markerId).firstOrNull()
- if (markerBean == null) {
- "无法查询到此ID【${markerId}】的信息".show(context)
- } else {
- detailDialog.setMarker(markerBean)
- detailDialog.show()
+ DataBaseManager.get.queryMarkerById(markerId).firstOrNull().apply {
+ if (this == null) {
+ "无法查询到此ID【${markerId}】的信息".show(context)
+ } else {
+ detailDialog.setMarker(this)
+ detailDialog.show()
+ }
}
}
}
@@ -582,7 +509,6 @@
}
}
}
- return true
}
override fun observeRequestState() {
@@ -865,9 +791,6 @@
override fun onResume() {
super.onResume()
binding.mapView.onResume()
- if (serialPortService != null) {
- openSerialPort()
- }
}
override fun onPause() {
@@ -885,8 +808,6 @@
binding.mapView.onDestroy()
soundPool.autoPause()
locationKit.stopLocation()
- unbindService(serviceConnection)
- closeSerialPort()
BaseApplication.get().closeSerialPort()
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/SatelliteStatusActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/SatelliteStatusActivity.kt
index 9f2d5cd..0f1611d 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/SatelliteStatusActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/SatelliteStatusActivity.kt
@@ -74,7 +74,7 @@
locationManager.registerGnssStatusCallback(gnssStatusListener, null)
satelliteAdapter = SatelliteRecyclerAdapter(this, satelliteCollection)
binding.recyclerView.adapter = satelliteAdapter
- binding.recyclerView.addItemDecoration(RecyclerViewItemDivider(1, Color.WHITE))
+ binding.recyclerView.addItemDecoration(RecyclerViewItemDivider(0f, 0f, Color.WHITE))
//高德定位
locationKit.getCurrentLocation(false, object : OnGetLocationListener {
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt
index c7c8bb9..5417e1f 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt
@@ -1,9 +1,5 @@
package com.casic.common.detector.gd.view
-import android.content.ComponentName
-import android.content.Context
-import android.content.Intent
-import android.content.ServiceConnection
import android.graphics.Color
import android.hardware.Sensor
import android.hardware.SensorEvent
@@ -13,9 +9,6 @@
import android.media.SoundPool
import android.os.Bundle
import android.os.CountDownTimer
-import android.os.Handler
-import android.os.IBinder
-import android.os.Message
import android.util.Log
import android.view.View
import android.view.WindowManager
@@ -25,28 +18,25 @@
import com.amap.api.maps.AMapUtils
import com.amap.api.maps.model.LatLng
import com.casic.common.detector.gd.R
+import com.casic.common.detector.gd.base.SerialPortActivity
import com.casic.common.detector.gd.callback.OnGetLocationListener
import com.casic.common.detector.gd.databinding.ActivitySearchMarkerBinding
import com.casic.common.detector.gd.extensions.toBuryDepth
import com.casic.common.detector.gd.extensions.toMarkerId
import com.casic.common.detector.gd.extensions.toSignalStrength
import com.casic.common.detector.gd.model.MarkerDistanceData
-import com.casic.common.detector.gd.service.SerialPortService
import com.casic.common.detector.gd.utils.CurrentSegment
import com.casic.common.detector.gd.utils.DataBaseManager
import com.casic.common.detector.gd.utils.LocaleConstant
import com.casic.common.detector.gd.utils.LocationKit
-import com.casic.common.detector.gd.utils.RuntimeCache
import com.casic.common.detector.gd.vm.TaskViewModel
import com.casic.common.detector.gd.widgets.RadarScanView
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.getSystemService
import com.pengxh.kt.lite.extensions.navigatePageTo
import com.pengxh.kt.lite.extensions.show
import com.pengxh.kt.lite.utils.LiteKitConstant
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.utils.SaveKeyValues
-import com.pengxh.kt.lite.utils.WeakReferenceHandler
import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -55,8 +45,8 @@
import java.util.TimerTask
import kotlin.math.atan2
-class SearchMarkerActivity : KotlinBaseActivity(),
- SensorEventListener, Handler.Callback {
+class SearchMarkerActivity : SerialPortActivity(),
+ SensorEventListener {
private val kTag = "SearchMarkerActivity"
private val context = this
@@ -76,38 +66,10 @@
private var signalEnergy = 0 //标识器信号强度
private var gravity: FloatArray? = null
private var geomagnetic: FloatArray? = null
- private var serialPortService: SerialPortService? = null
- private lateinit var searchSignalEnergyTimer: Timer
-
- private val serviceConnection = object : ServiceConnection {
- override fun onServiceConnected(name: ComponentName?, iBinder: IBinder?) {
- if (name != null && iBinder != null && iBinder is SerialPortService.ServiceBinder) {
- try {
- serialPortService = iBinder.getSerialPortService()
- Log.d(kTag, "onServiceConnected: 服务已绑定,开始搜索标识器")
- searchMarker()
- } catch (e: Exception) {
- Log.e(kTag, "onServiceConnected: 绑定服务时发生异常", e)
- }
- } else {
- Log.w(kTag, "onServiceConnected: name 或 iBinder 为 null")
- }
- }
-
- override fun onServiceDisconnected(name: ComponentName?) {
-
- }
- }
-
- companion object {
- var weakReferenceHandler: WeakReferenceHandler? = null
- }
override fun initOnCreate(savedInstanceState: Bundle?) {
- weakReferenceHandler = WeakReferenceHandler(this)
-
- val flag = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY) as String
- isExecuteTask = flag != "0"
+ val taskState = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY) as String
+ isExecuteTask = taskState != "0"
slowSoundResourceId = soundPool.load(this, R.raw.ring4, 1)
fastSoundResourceId = soundPool.load(this, R.raw.ring2, 1)
@@ -131,14 +93,11 @@
binding.taskStateView.isSelected = true
}
- //绑定串口通信服务
- Intent(this, SerialPortService::class.java).also {
- bindService(it, serviceConnection, Context.BIND_AUTO_CREATE)
- }
+ openSerialPort()
+ searchMarker(CurrentSegment.SearchMarker)
//在标识器信号强度很强的时候,从数据库中计算出距离最近的点,以防出现探测不到ID的情况
- searchSignalEnergyTimer = Timer()
- searchSignalEnergyTimer.schedule(object : TimerTask() {
+ Timer().schedule(object : TimerTask() {
override fun run() {
if (signalEnergy <= 700) {//18°
runOnUiThread {
@@ -183,21 +142,8 @@
}, 0, 2000)
}
- private val countDownTimer = object : CountDownTimer(10 * 1000, 1000) {
- override fun onTick(millisUntilFinished: Long) {
-
- }
-
- override fun onFinish() {
- LoadingDialog.dismiss()
- "标识器深度探测超时,请移动位置重试".show(context)
- searchMarker()
- }
- }
-
override fun initEvent() {
binding.depthButton.setOnClickListener {
- soundPool.autoPause()
val result = DataBaseManager.get.queryMarkerById(markerId)
if (result.isNotEmpty()) {
val tag = when (result.first().markerType) {
@@ -208,18 +154,25 @@
}
if (tag == '1') {
"此标识器无法读取埋深!".show(this)
- searchMarker()
} else {
+ soundPool.autoPause()
LoadingDialog.show(this, "正在探测标识器埋深,请稍后...")
- countDownTimer.start()
// 发送读取标识器埋设深度指令
- RuntimeCache.currentSegment = CurrentSegment.DetectMarkerDepth
- serialPortService?.writeCommand(tag)
+ detectDepth(tag)
+ object : CountDownTimer(3 * 1000, 1000) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ LoadingDialog.dismiss()
+ updateSegment(CurrentSegment.SearchMarker)
+ }
+ }.start()
}
} else {
LoadingDialog.dismiss()
"标识器未安装,安装成功后才可读取埋深!".show(this)
- searchMarker()
}
}
@@ -236,13 +189,11 @@
}
}
- override fun handleMessage(msg: Message): Boolean {
- val buffer = msg.obj as ByteArray
- if (msg.what == LocaleConstant.DETECT_MARKER_DEPTH) {
- val tag = (buffer.first().toInt() and 0xFF).toString(16).uppercase()
- if (tag == "53") {
+ override fun onDataReceived(buffer: ByteArray, segment: CurrentSegment) {
+ if (segment == CurrentSegment.DetectDepth) {
+ val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase()
+ if (flag == "53" && buffer.size == 5) {
LoadingDialog.dismiss()
- countDownTimer.cancel()
try {
AlertMessageDialog.Builder().setContext(context)
.setTitle("温馨提示")
@@ -251,54 +202,32 @@
.setOnDialogButtonClickListener(object :
AlertMessageDialog.OnDialogButtonClickListener {
override fun onConfirmClick() {
- searchMarker()
+ updateSegment(CurrentSegment.SearchMarker)
}
}).build().show()
} catch (e: WindowManager.BadTokenException) {
e.printStackTrace()
- } catch (e: NumberFormatException) {
- e.printStackTrace()
}
}
- } else if (msg.what == LocaleConstant.SEARCH_MARKER) {
- try {
- // 读取到信号强度
- when ((buffer.first().toInt() and 0xFF).toString(16).uppercase()) {
- "4E" -> {
- val signalEnergy = buffer.toSignalStrength()
+ } else if (segment == CurrentSegment.SearchMarker) {
+ val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase()
+ if (flag == "30" && buffer.size == 10) {
+ handleMarker(buffer.toMarkerId())
+ } else if (flag == "4E" && buffer.size == 5) {
+ val signalEnergy = buffer.toSignalStrength()
- //声音
- updateSound(signalEnergy)
+ //声音
+ updateSound(signalEnergy)
- //信号强度显示
- updateProgressBar(signalEnergy)
+ //信号强度显示
+ updateProgressBar(signalEnergy)
- //搜索信号文字显示
- updateTextResult(signalEnergy)
- }
-
- "30" -> {
- handleMarker(buffer.toMarkerId())
- }
-
- else -> {
- Log.d(kTag, "乱码数据: ${buffer.contentToString()}")
- }
- }
- } catch (e: Exception) {
- e.printStackTrace()
- Log.e(kTag, "Error processing buffer data", e)
+ //搜索信号文字显示
+ updateTextResult(signalEnergy)
+ } else {
+ Log.d(kTag, "乱码数据: ${buffer.contentToString()}")
}
}
- return true
- }
-
- /**
- * 搜索标识器
- * */
- private fun searchMarker() {
- RuntimeCache.currentSegment = CurrentSegment.SearchMarker
- serialPortService?.writeCommand('2', '6')
}
private fun updateSound(signalEnergy: Int) {
@@ -492,9 +421,8 @@
override fun onDestroy() {
super.onDestroy()
+ closeSerialPort()
soundPool.autoPause()
- RuntimeCache.currentSegment = null
locationKit.stopLocation()
- unbindService(serviceConnection)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/VersionControlActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/VersionControlActivity.kt
index ddc5a32..8641c79 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/VersionControlActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/VersionControlActivity.kt
@@ -13,17 +13,17 @@
import com.casic.common.detector.gd.databinding.ActivityVersionControlBinding
import com.casic.common.detector.gd.extensions.appendDownloadUrl
import com.casic.common.detector.gd.extensions.initImmersionBar
-import com.casic.common.detector.gd.utils.FileDownloadManager
import com.casic.common.detector.gd.utils.FileType
import com.casic.common.detector.gd.vm.VersionViewModel
-import com.casic.common.detector.gd.widgets.ProgressDialog
import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.createDownloadFileDir
import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.FileDownloadManager
import com.pengxh.kt.lite.utils.LoadState
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.widget.TitleBarView
import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.ProgressDialog
import java.io.File
class VersionControlActivity : KotlinBaseActivity() {
@@ -118,7 +118,7 @@
installApk(file)
}
- override fun onFailed(t: Throwable) {
+ override fun onDownloadFailed(t: Throwable) {
t.printStackTrace()
progressDialog.dismiss()
}
diff --git a/app/src/main/java/com/casic/common/detector/gd/widgets/ProgressDialog.kt b/app/src/main/java/com/casic/common/detector/gd/widgets/ProgressDialog.kt
deleted file mode 100644
index af480b0..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/widgets/ProgressDialog.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.casic.common.detector.gd.widgets
-
-import android.app.Dialog
-import android.content.Context
-import android.os.Bundle
-import com.casic.common.detector.gd.databinding.DialogProgressBinding
-import com.pengxh.kt.lite.R
-import com.pengxh.kt.lite.extensions.binding
-import com.pengxh.kt.lite.extensions.initDialogLayoutParams
-
-class ProgressDialog(context: Context) : Dialog(context, R.style.UserDefinedDialogStyle) {
-
- private val binding: DialogProgressBinding by binding()
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- this.initDialogLayoutParams(0.5f)
- setCanceledOnTouchOutside(false)
- setCancelable(false)
- binding.progressBar.progress = 0
- binding.progressText.text = "0 %"
- }
-
- fun setMaxProgress(maxProgress: Long) {
- binding.progressBar.max = maxProgress.toInt()
- }
-
- private fun getMaxProgress() = binding.progressBar.max
-
- fun updateProgress(progress: Long) {
- binding.progressBar.progress = progress.toInt()
-
- val percent = (progress.toFloat() / getMaxProgress()) * 100
- binding.progressText.text = String.format("%.2f %%", percent)
- }
-}
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index c9b11ec..1a81160 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -77,7 +77,7 @@
dependencies {
//基础依赖库
- implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.1'
+ implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.3'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
//Google官方授权框架
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2f152d8..5c645f0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -91,7 +91,6 @@
android:resource="@xml/file_paths" />
-
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
index 6cb496c..e5fe1f5 100644
--- a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
@@ -1,6 +1,7 @@
package com.casic.common.detector.gd.base
import android.app.Application
+import android.util.Log
import com.casic.common.detector.gd.greendao.DaoMaster
import com.casic.common.detector.gd.greendao.DaoSession
import com.casic.common.detector.gd.uart.SerialPort
@@ -52,6 +53,7 @@
//千寻报文数据下发串口号
add(SerialPort(File("/dev/ttyS1"), 9600, 0))
}
+ Log.d(kTag, "onCreate: 已初始化 ${serialPorts.size} 个串口")
} catch (e: SecurityException) {
"您没有串口的读写权限!".show(this)
} catch (e: IOException) {
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
new file mode 100644
index 0000000..08b3e19
--- /dev/null
+++ b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
@@ -0,0 +1,204 @@
+package com.casic.common.detector.gd.base
+
+import android.os.Bundle
+import android.os.Handler
+import android.os.Message
+import android.util.Log
+import androidx.appcompat.app.AppCompatActivity
+import androidx.viewbinding.ViewBinding
+import com.casic.common.detector.gd.utils.CurrentSegment
+import com.casic.common.detector.gd.utils.GpioManager
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import java.io.IOException
+import java.util.Timer
+import java.util.TimerTask
+import java.util.concurrent.atomic.AtomicInteger
+
+abstract class SerialPortActivity : AppCompatActivity(), Handler.Callback {
+
+ private val kTag = "SerialPortActivity"
+ private val taskTimer by lazy { Timer() }
+ private val weakReferenceHandler by lazy { WeakReferenceHandler(this) }
+
+ //输出流
+ private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
+
+ //输入流
+ private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
+ private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
+
+ private var segment: CurrentSegment? = null
+
+ protected lateinit var binding: VB
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = initViewBinding()
+ setContentView(binding.root)
+ setupTopBarLayout()
+ initOnCreate(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = firstInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = lastInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+ }
+
+ /**
+ * 初始化ViewBinding
+ */
+ abstract fun initViewBinding(): VB
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initOnCreate(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ abstract fun onDataReceived(buffer: ByteArray, segment: CurrentSegment)
+
+ override fun handleMessage(msg: Message): Boolean {
+ if (msg.what == 2025012001) {
+ val bytes = msg.obj as ByteArray
+ if (segment == null) {
+ return true
+ }
+ Log.d(kTag, "$segment - ${bytes.contentToString()}")
+ onDataReceived(bytes, segment!!)
+ }
+ return true
+ }
+
+ private var readMarkerIdTask: TimerTask? = null
+ private var searchMarkerTask: TimerTask? = null
+
+ fun readMarkerId() {
+ this.segment = CurrentSegment.InstallMarker
+ readMarkerIdTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(readMarkerIdTask, 0, 300)
+ }
+
+ fun detectDepth(tag: Char) {
+ this.segment = CurrentSegment.DetectDepth
+ outStream.write('3'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write(tag.code)
+ outStream.flush()
+ }
+
+ fun updateSegment(segment: CurrentSegment) {
+ this.segment = segment
+ }
+
+ fun searchMarker(segment: CurrentSegment) {
+ this.segment = segment
+ searchMarkerTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write('6'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(searchMarkerTask, 0, 300)
+ }
+
+ /***************************************************************************************/
+ private val gpioManager by lazy { GpioManager() }
+
+ /**
+ * 读取数据 1
+ * 暂停读取 0
+ * */
+ private val gpioState = AtomicInteger(0)
+ fun openSerialPort() {
+ if (gpioState.get() != 1) {
+ gpioManager.setGpioHigh("18")
+ gpioState.set(1)
+ Log.d(kTag, "openSerialPort: 调高串口电位")
+ } else {
+ Log.d(kTag, "openSerialPort: 已经是高电位,直接读数据")
+ }
+ }
+
+ fun closeSerialPort() {
+ if (segment != null) {
+ segment = null
+ }
+ readMarkerIdTask?.cancel()
+ searchMarkerTask?.cancel()
+ if (gpioState.get() == 0) {
+ Log.d(kTag, "closeSerialPort: 已经是低电位,不响应")
+ return
+ }
+ // 降低串口电位
+ gpioManager.setGpioLow("18")
+ gpioState.set(0)
+ Log.d(kTag, "closeSerialPort: 降低串口电位")
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ closeSerialPort()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
index 442189e..5c3ee01 100644
--- a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
@@ -1,42 +1,20 @@
package com.casic.common.detector.gd.extensions
-import android.util.Log
-
/**
* 因为数据频率很高,而且每一帧数据至少有一个信号值,如果有多个信号强度值,取平均值
*
* [78, 53, 49, 55, 51]
*
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
* */
fun ByteArray.toSignalStrength(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var strength = 0
+ for (byte in dataBytes) {
+ strength = strength * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return strength
}
/**
@@ -44,32 +22,13 @@
*
* [48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
*
- * [48, 48, 48, 56, 56, 57, 49, 48, 55, 51, 48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
- *
* */
fun ByteArray.toMarkerId(): String {
- //判断数据合理性
- val validBytes = if (this.size % 10 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 10) * 10
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ val id = this.map { it.toInt().toChar() }.joinToString("")
+ if (id.matches("-?\\d+".toRegex())) {
+ return id
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 10) {
- // 每10个字节取一次数据转为ASCII
- val tempBytes = validBytes.sliceArray(i until minOf(i + 10, validBytes.size))
- val string = tempBytes.map { it.toInt().toChar() }.joinToString("")
- if (string.matches("-?\\d+".toRegex())) {
- list.add(string)
- } else {
- Log.d("kTag", "toDeviceCode: 编号解析失败")
- }
- }
- return list.last()
+ return ""
}
/**
@@ -77,31 +36,14 @@
*
* [83, 48, 48, 48, 57]
*
- * [83, 48, 48, 48, 57, 83, 48, 48, 48, 57]
* */
fun ByteArray.toBuryDepth(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var depth = 0
+ for (byte in dataBytes) {
+ depth = depth * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return depth
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt b/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
deleted file mode 100644
index 76cf583..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
+++ /dev/null
@@ -1,136 +0,0 @@
-package com.casic.common.detector.gd.service
-
-import android.app.Service
-import android.content.Intent
-import android.os.Binder
-import android.os.IBinder
-import android.util.Log
-import com.casic.common.detector.gd.base.BaseApplication
-import com.casic.common.detector.gd.utils.CurrentSegment
-import com.casic.common.detector.gd.utils.LocaleConstant
-import com.casic.common.detector.gd.utils.RuntimeCache
-import com.casic.common.detector.gd.view.InstallMarkerActivity
-import com.casic.common.detector.gd.view.MainActivity
-import com.casic.common.detector.gd.view.SearchMarkerActivity
-import java.io.IOException
-import java.io.InputStream
-import java.util.concurrent.Executors
-import java.util.concurrent.TimeUnit
-
-class SerialPortService : Service() {
-
- private val kTag = "SerialPortService"
- private val sendExecutor = Executors.newFixedThreadPool(5)
- private val readExecutor = Executors.newSingleThreadScheduledExecutor()
-
- //输出流
- private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
-
- //输入流
- private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
- private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
-
- override fun onCreate() {
- super.onCreate()
- try {
- // 使用单线程调度器读取数据
- readExecutor.scheduleAtFixedRate({
- readData(firstInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
-
- readExecutor.scheduleAtFixedRate({
- readData(lastInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- private fun readData(inputStream: InputStream) {
- try {
- val buffer = ByteArray(1024)
- var bytesRead: Int
- while (inputStream.available() > 0) {
- bytesRead = inputStream.read(buffer)
- if (bytesRead > 0) {
- when (RuntimeCache.currentSegment) {
- CurrentSegment.DetectMarkerDepth -> {
- //深度
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.DETECT_MARKER_DEPTH
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.InstallMarker -> {
- //安装点
- InstallMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.INSTALL_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.FreeInspection -> {
- //自由巡检
- MainActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.FREE_INSPECTION
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.SearchMarker -> {
- //搜索标识器
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.SEARCH_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- else -> {
- val bytes = buffer.copyOf(bytesRead)
- Log.d(kTag, "空状态,不处理 ===> ${bytes.contentToString()}")
- }
- }
- }
- }
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- fun writeCommand(vararg command: Char) {
- Log.d(kTag, "writeCommand: ${command.contentToString()}")
- if (command.size == 1) {
- sendExecutor.submit {
- outStream.write(command.first().code)
- outStream.flush()
- }
- } else {
- command.forEach {
- sendExecutor.submit {
- outStream.write(it.code)
- outStream.flush()
- }
- Thread.sleep(1000)
- }
- }
- }
-
- override fun onBind(intent: Intent?): IBinder {
- return ServiceBinder()
- }
-
- inner class ServiceBinder : Binder() {
- fun getSerialPortService(): SerialPortService {
- return this@SerialPortService
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt b/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
index 0606b72..9efa097 100644
--- a/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
@@ -1,23 +1,23 @@
package com.casic.common.detector.gd.utils
-sealed class CurrentSegment {
+enum class CurrentSegment {
/**
* 安装标识器
* */
- object InstallMarker : CurrentSegment()
+ InstallMarker,
/**
* 自由巡检
* */
- object FreeInspection : CurrentSegment()
+ FreeInspection,
/**
* 搜索标识器
* */
- object SearchMarker : CurrentSegment()
+ SearchMarker,
/**
* 探测标识器深度
* */
- object DetectMarkerDepth : CurrentSegment()
+ DetectDepth
}
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt
deleted file mode 100644
index c9151a8..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt
+++ /dev/null
@@ -1,150 +0,0 @@
-package com.casic.common.detector.gd.utils
-
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.SupervisorJob
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import okhttp3.Call
-import okhttp3.Callback
-import okhttp3.OkHttpClient
-import okhttp3.Request
-import okhttp3.Response
-import java.io.File
-import java.io.IOException
-import java.util.concurrent.atomic.AtomicBoolean
-
-class FileDownloadManager(builder: Builder) {
-
- private val httpClient by lazy { OkHttpClient() }
-
- class Builder {
- lateinit var url: String
- lateinit var suffix: String
- lateinit var directory: File
- lateinit var downloadListener: OnFileDownloadListener
-
- /**
- * 文件下载地址
- * */
- fun setDownloadFileSource(url: String): Builder {
- this.url = url
- return this
- }
-
- /**
- * 文件后缀
- * 如:apk等
- * */
- fun setFileSuffix(suffix: String): Builder {
- this.suffix = if (suffix.contains(".")) {
- //去掉前缀的点
- suffix.drop(1)
- } else {
- suffix
- }
- return this
- }
-
- /**
- * 文件保存的地址
- * */
- fun setFileSaveDirectory(directory: File): Builder {
- this.directory = directory
- return this
- }
-
- /**
- * 设置文件下载回调监听
- * */
- fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder {
- this.downloadListener = downloadListener
- return this
- }
-
- fun build(): FileDownloadManager {
- if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) {
- throw IllegalStateException("All properties must be initialized before building.")
- }
- return FileDownloadManager(this)
- }
- }
-
- private val url = builder.url
- private val suffix = builder.suffix
- private val directory = builder.directory
- private val listener = builder.downloadListener
-
- /**
- * 开始下载
- * */
- fun start() {
- val job = SupervisorJob()
- val scope = CoroutineScope(Dispatchers.Main + job)
-
- val request = Request.Builder().get().url(url).build()
- val newCall = httpClient.newCall(request)
- val isExecuting = AtomicBoolean(false)
-
- /**
- * 如果已被加入下载队列,则取消之前的,重新下载
- */
- if (isExecuting.getAndSet(true)) {
- newCall.cancel()
- }
-
- //异步下载文件
- newCall.enqueue(object : Callback {
- override fun onFailure(call: Call, e: IOException) {
- scope.launch(Dispatchers.Main) {
- listener.onFailed(e)
- }
- }
-
- override fun onResponse(call: Call, response: Response) {
- scope.launch(Dispatchers.IO) {
- val body = response.body
- if (body == null) {
- listener.onFailed(IOException("Response body is null"))
- throw IOException("Response body is null")
- } else {
- val inputStream = body.byteStream()
- val fileSize = body.contentLength()
-
- if (fileSize <= 0) {
- throw IllegalArgumentException("Invalid file size")
- }
- listener.onDownloadStart(fileSize)
-
- val file = File(directory, "${System.currentTimeMillis()}.${suffix}")
- file.outputStream().use { fos ->
- val buffer = ByteArray(2048)
- var sum = 0L
- var read: Int
- while (inputStream.read(buffer).also { read = it } != -1) {
- fos.write(buffer, 0, read)
- sum += read.toLong()
- withContext(Dispatchers.Main) {
- listener.onProgressChanged(sum)
- }
- }
- }
-
- withContext(Dispatchers.Main) {
- listener.onDownloadEnd(file)
- }
-
- job.cancel()
- }
- }
- }
- })
- }
-
- interface OnFileDownloadListener {
- fun onDownloadStart(total: Long)
- fun onProgressChanged(progress: Long)
- fun onDownloadEnd(file: File)
- fun onFailed(t: Throwable)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt b/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
index 2334680..c658924 100644
--- a/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
@@ -14,10 +14,6 @@
const val PERMISSIONS_CODE = 999
const val MAX_DISTANCE = 5.5f //表盘最大显示距离
- const val FREE_INSPECTION = 20250101
- const val INSTALL_MARKER = 20250102
- const val DETECT_MARKER_DEPTH = 20250103
- const val SEARCH_MARKER = 20250104
const val AUTO_SAVE = "AUTO_SAVE"
const val USER_ACCOUNT = "USER_ACCOUNT"
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt b/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt
deleted file mode 100644
index 104f971..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.casic.common.detector.gd.utils
-
-object RuntimeCache {
- var currentSegment: CurrentSegment? = null
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt
index c5f18a6..b3dce3c 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt
@@ -1,26 +1,19 @@
package com.casic.common.detector.gd.view
import android.app.DatePickerDialog
-import android.content.ComponentName
-import android.content.Context
import android.content.DialogInterface
-import android.content.Intent
-import android.content.ServiceConnection
import android.hardware.Camera
import android.media.AudioAttributes
import android.media.SoundPool
import android.os.Bundle
import android.os.CountDownTimer
-import android.os.Handler
-import android.os.IBinder
-import android.os.Message
-import android.util.Log
import android.view.View
import android.widget.AdapterView
import androidx.lifecycle.ViewModelProvider
import com.amap.api.location.AMapLocation
import com.casic.common.detector.gd.R
import com.casic.common.detector.gd.adapter.EditableImageAdapter
+import com.casic.common.detector.gd.base.SerialPortActivity
import com.casic.common.detector.gd.bean.MarkerLocalBean
import com.casic.common.detector.gd.callback.OnGetLocationListener
import com.casic.common.detector.gd.callback.OnImageCompressListener
@@ -33,18 +26,15 @@
import com.casic.common.detector.gd.extensions.toColor
import com.casic.common.detector.gd.extensions.toMarkerId
import com.casic.common.detector.gd.extensions.toObjectType
-import com.casic.common.detector.gd.service.SerialPortService
import com.casic.common.detector.gd.utils.CurrentSegment
import com.casic.common.detector.gd.utils.DataBaseManager
import com.casic.common.detector.gd.utils.LocaleConstant
import com.casic.common.detector.gd.utils.LocationKit
-import com.casic.common.detector.gd.utils.RuntimeCache
import com.casic.common.detector.gd.vm.TaskViewModel
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.appendZero
import com.pengxh.kt.lite.extensions.dateToTimestamp
import com.pengxh.kt.lite.extensions.navigatePageTo
@@ -55,13 +45,12 @@
import com.pengxh.kt.lite.utils.LoadState
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.utils.SaveKeyValues
-import com.pengxh.kt.lite.utils.WeakReferenceHandler
import com.pengxh.kt.lite.widget.TitleBarView
import java.io.File
import java.util.Calendar
import java.util.Date
-class InstallMarkerActivity : KotlinBaseActivity(), Handler.Callback {
+class InstallMarkerActivity : SerialPortActivity() {
private val kTag = "InstallMarkerActivity"
private val context = this
@@ -73,7 +62,6 @@
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build()
private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build()
private var soundResourceId = 0
- private var serialPortService: SerialPortService? = null
private lateinit var imageAdapter: EditableImageAdapter
override fun initEvent() {
@@ -255,18 +243,18 @@
//读标识器
binding.readMarkerButton.setOnClickListener {
+ openSerialPort()
LoadingDialog.show(this, "标识器读取中,请稍后...")
countDownTimer.start()
binding.readMarkerButton.isEnabled = false
- RuntimeCache.currentSegment = CurrentSegment.InstallMarker
- serialPortService?.writeCommand('2')
+ readMarkerId()
}
}
- override fun handleMessage(msg: Message): Boolean {
- if (msg.what == LocaleConstant.INSTALL_MARKER) {
- val buffer = msg.obj as ByteArray
- if ((buffer.first().toInt() and 0xFF).toString(16).uppercase() == "30") {
+ override fun onDataReceived(buffer: ByteArray, segment: CurrentSegment) {
+ if (segment == CurrentSegment.InstallMarker) {
+ val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase()
+ if (flag == "30" && buffer.size == 10) {
val markerId = buffer.toMarkerId()
LoadingDialog.dismiss()
countDownTimer.cancel()
@@ -274,7 +262,6 @@
binding.identifierInclude.identifierIdView.text = markerId
}
}
- return true
}
/**
@@ -363,37 +350,7 @@
})
}
- private val serviceConnection = object : ServiceConnection {
- override fun onServiceConnected(name: ComponentName?, iBinder: IBinder?) {
- if (name != null && iBinder != null && iBinder is SerialPortService.ServiceBinder) {
- try {
- serialPortService = iBinder.getSerialPortService()
- Log.d(kTag, "onServiceConnected: 服务已绑定")
- } catch (e: Exception) {
- Log.e(kTag, "onServiceConnected: 绑定服务时发生异常", e)
- }
- } else {
- Log.w(kTag, "onServiceConnected: name 或 iBinder 为 null")
- }
- }
-
- override fun onServiceDisconnected(name: ComponentName?) {
- //在连接正常关闭的情况下不会被调用, 只在Service被破坏了或者被杀死的时候调用
- }
- }
-
- companion object {
- var weakReferenceHandler: WeakReferenceHandler? = null
- }
-
override fun initOnCreate(savedInstanceState: Bundle?) {
- weakReferenceHandler = WeakReferenceHandler(this)
-
- //绑定串口通信服务
- Intent(this, SerialPortService::class.java).also {
- bindService(it, serviceConnection, Context.BIND_AUTO_CREATE)
- }
-
locationKit.getCurrentLocation(true, object : OnGetLocationListener {
override fun onSuccess(location: AMapLocation) {
binding.identifierInclude.lngView.text = location.longitude.toString()
@@ -552,8 +509,6 @@
override fun onDestroy() {
super.onDestroy()
- RuntimeCache.currentSegment = null
locationKit.stopLocation()
- unbindService(serviceConnection)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt
index 8a798b6..2c48cc9 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt
@@ -1,18 +1,12 @@
package com.casic.common.detector.gd.view
import android.app.Activity
-import android.content.ComponentName
-import android.content.Context
import android.content.Intent
-import android.content.ServiceConnection
import android.graphics.BitmapFactory
import android.graphics.Color
import android.media.AudioAttributes
import android.media.SoundPool
import android.os.Bundle
-import android.os.Handler
-import android.os.IBinder
-import android.os.Message
import android.util.Log
import android.view.KeyEvent
import android.view.View
@@ -34,6 +28,7 @@
import com.amap.api.maps.model.MyLocationStyle
import com.casic.common.detector.gd.R
import com.casic.common.detector.gd.base.BaseApplication
+import com.casic.common.detector.gd.base.SerialPortActivity
import com.casic.common.detector.gd.bean.MarkerLocalBean
import com.casic.common.detector.gd.bean.TaskLocalBean
import com.casic.common.detector.gd.callback.OnGetAddressListener
@@ -47,32 +42,27 @@
import com.casic.common.detector.gd.model.TaskDetailLocalModel
import com.casic.common.detector.gd.model.TaskModel
import com.casic.common.detector.gd.service.NtripConnectService
-import com.casic.common.detector.gd.service.SerialPortService
import com.casic.common.detector.gd.utils.CurrentSegment
import com.casic.common.detector.gd.utils.DataBaseManager
import com.casic.common.detector.gd.utils.ExcelKit
-import com.casic.common.detector.gd.utils.FileDownloadManager
import com.casic.common.detector.gd.utils.FileType
-import com.casic.common.detector.gd.utils.GpioManager
import com.casic.common.detector.gd.utils.LocaleConstant
import com.casic.common.detector.gd.utils.LocationKit
import com.casic.common.detector.gd.utils.RouteOnMap
-import com.casic.common.detector.gd.utils.RuntimeCache
import com.casic.common.detector.gd.vm.TaskViewModel
import com.casic.common.detector.gd.widgets.MarkerDetailDialog
import com.casic.common.detector.gd.widgets.QueryMarkerDialog
import com.casic.common.detector.gd.widgets.SamplePopupWindow
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.createDownloadFileDir
import com.pengxh.kt.lite.extensions.dp2px
import com.pengxh.kt.lite.extensions.isNetworkConnected
import com.pengxh.kt.lite.extensions.navigatePageTo
import com.pengxh.kt.lite.extensions.show
import com.pengxh.kt.lite.extensions.timestampToCompleteDate
+import com.pengxh.kt.lite.utils.FileDownloadManager
import com.pengxh.kt.lite.utils.LoadState
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.utils.SaveKeyValues
-import com.pengxh.kt.lite.utils.WeakReferenceHandler
import com.pengxh.kt.lite.widget.TitleBarView
import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
import com.pengxh.kt.lite.widget.dialog.AlertInputDialog
@@ -82,45 +72,13 @@
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
-import java.util.concurrent.atomic.AtomicInteger
-class MainActivity : KotlinBaseActivity(), AMap.OnMarkerClickListener,
- OnMapLongClickListener, Handler.Callback {
+class MainActivity : SerialPortActivity(), AMap.OnMarkerClickListener,
+ OnMapLongClickListener {
private val kTag = "MainActivity"
private val context = this
-
- /***************************************************************************************/
- private val gpioManager by lazy { GpioManager() }
-
- /**
- * 读取数据 1
- * 暂停读取 0
- * */
- private val gpioState = AtomicInteger(0)
- private fun openSerialPort() {
- if (gpioState.get() != 1) {
- gpioManager.setGpioHigh("18")
- gpioState.set(1)
- Log.d(kTag, "openSerialPort: 调高串口电位")
- } else {
- Log.d(kTag, "openSerialPort: 已经是高电位,直接读数据")
- }
- }
-
- private fun closeSerialPort() {
- if (gpioState.get() == 0) {
- Log.d(kTag, "closeSerialPort: 已经是低电位,直接返回")
- return
- }
- // 降低串口电位
- gpioManager.setGpioLow("18")
- gpioState.set(0)
- Log.d(kTag, "closeSerialPort: 降低串口电位")
- }
-
- /***************************************************************************************/
private val samplePopupWindow by lazy { SamplePopupWindow(this) }
private val detailDialog by lazy { MarkerDetailDialog(this) }
private val locationKit by lazy { LocationKit(this) }
@@ -133,7 +91,6 @@
private var freeTaskTitle = ""
private var ids = HashSet()
private var freeTaskId: String? = null
- private var serialPortService: SerialPortService? = null
private var soundResourceId = 0
private var isExecuteTask = false
private lateinit var aMap: AMap
@@ -146,43 +103,13 @@
binding.rootView.initImmersionBar(this, false, R.color.themeColor)
}
- private val serviceConnection = object : ServiceConnection {
- override fun onServiceConnected(name: ComponentName?, iBinder: IBinder?) {
- if (name != null && iBinder != null && iBinder is SerialPortService.ServiceBinder) {
- try {
- serialPortService = iBinder.getSerialPortService()
- Log.d(kTag, "onServiceConnected: 服务已绑定")
- openSerialPort()
- } catch (e: Exception) {
- Log.e(kTag, "onServiceConnected: 绑定服务时发生异常", e)
- }
- } else {
- Log.w(kTag, "onServiceConnected: name 或 iBinder 为 null")
- }
- }
-
- override fun onServiceDisconnected(name: ComponentName?) {
-
- }
- }
-
- companion object {
- var weakReferenceHandler: WeakReferenceHandler? = null
- }
-
override fun initOnCreate(savedInstanceState: Bundle?) {
- weakReferenceHandler = WeakReferenceHandler(this)
-
//地图初始化
initMapConfig(savedInstanceState)
- //绑定串口通信服务
- Intent(this, SerialPortService::class.java).also {
- bindService(it, serviceConnection, Context.BIND_AUTO_CREATE)
- }
- Intent(this, NtripConnectService::class.java).also {
- startService(it)
- }
+// Intent(this, NtripConnectService::class.java).also {
+// startService(it)
+// }
soundResourceId = soundPool.load(this, R.raw.ring3, 1)
//右上角菜单
@@ -211,7 +138,7 @@
showMarkersOnMap()
}
- override fun onFailed(t: Throwable) {
+ override fun onDownloadFailed(t: Throwable) {
t.printStackTrace()
}
@@ -446,7 +373,7 @@
override fun onConfirmClick() {
isFreeTask = false
soundPool.autoPause()
- RuntimeCache.currentSegment = null
+ closeSerialPort()
binding.stopFreeTaskButton.visibility = View.GONE
if (freeTaskId.isNullOrBlank()) {
@@ -499,11 +426,7 @@
} else {
"此工单下无标识器,将执行自由巡检任务".show(context)
freeTaskId = task.taskId
-
- binding.stopFreeTaskButton.visibility = View.VISIBLE
- isFreeTask = true
- RuntimeCache.currentSegment = CurrentSegment.FreeInspection
- serialPortService?.writeCommand('2', '6')
+ detectMarker()
}
}
@@ -524,21 +447,22 @@
freeTaskTitle = value
val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String
taskViewModel.createFreeTask(context, userId, value)
-
- binding.stopFreeTaskButton.visibility = View.VISIBLE
- isFreeTask = true
- RuntimeCache.currentSegment = CurrentSegment.FreeInspection
- serialPortService?.writeCommand('2', '6')
+ detectMarker()
}
override fun onCancelClick() {}
}).build().show()
}
- override fun handleMessage(msg: Message): Boolean {
- if (msg.what == LocaleConstant.FREE_INSPECTION) {
- val buffer = msg.obj as ByteArray
- //只响一次,因为探测频率高,所以依旧是连续的报警声
+ private fun detectMarker() {
+ binding.stopFreeTaskButton.visibility = View.VISIBLE
+ isFreeTask = true
+ openSerialPort()
+ searchMarker(CurrentSegment.FreeInspection)
+ }
+
+ override fun onDataReceived(buffer: ByteArray, segment: CurrentSegment) {
+ if (segment == CurrentSegment.FreeInspection) {
soundPool.play(soundResourceId, 1f, 1f, 0, 0, 1f)
when ((buffer.first().toInt() and 0xFF).toString(16).uppercase()) {
"4E" -> {
@@ -552,27 +476,30 @@
val markerId = buffer.toMarkerId()
//添加地图Marker
if (!ids.contains(markerId)) {
- //根据markerId查询标识器经纬度
- val labels = DataBaseManager.get.queryMarkerById(markerId)
- if (labels.isNotEmpty()) {
- val bean = labels.first()
- aMap.addMarker(
- MarkerOptions()
- .position(LatLng(bean.lat.toDouble(), bean.lng.toDouble()))
- .icon(BitmapDescriptorFactory.fromResource(R.mipmap.label_blue1))
+ val markers = DataBaseManager.get.queryMarkerById(markerId)
+ if (markers.isNotEmpty()) {
+ val marker = markers.first()
+ val latLng = LatLng(
+ marker.lat.toDouble(), marker.lng.toDouble()
)
+ val resource = BitmapDescriptorFactory.fromResource(
+ R.mipmap.label_blue1
+ )
+ val options = MarkerOptions().position(latLng).icon(resource)
+ aMap.addMarker(options)
}
}
ids.add(markerId)
//显示标识器详细信息
if (!detailDialog.isShowing) {
- val markerBean = DataBaseManager.get.queryMarkerById(markerId).firstOrNull()
- if (markerBean == null) {
- "无法查询到此ID【${markerId}】的信息".show(context)
- } else {
- detailDialog.setMarker(markerBean)
- detailDialog.show()
+ DataBaseManager.get.queryMarkerById(markerId).firstOrNull().apply {
+ if (this == null) {
+ "无法查询到此ID【${markerId}】的信息".show(context)
+ } else {
+ detailDialog.setMarker(this)
+ detailDialog.show()
+ }
}
}
}
@@ -582,7 +509,6 @@
}
}
}
- return true
}
override fun observeRequestState() {
@@ -865,9 +791,6 @@
override fun onResume() {
super.onResume()
binding.mapView.onResume()
- if (serialPortService != null) {
- openSerialPort()
- }
}
override fun onPause() {
@@ -885,8 +808,6 @@
binding.mapView.onDestroy()
soundPool.autoPause()
locationKit.stopLocation()
- unbindService(serviceConnection)
- closeSerialPort()
BaseApplication.get().closeSerialPort()
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/SatelliteStatusActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/SatelliteStatusActivity.kt
index 9f2d5cd..0f1611d 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/SatelliteStatusActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/SatelliteStatusActivity.kt
@@ -74,7 +74,7 @@
locationManager.registerGnssStatusCallback(gnssStatusListener, null)
satelliteAdapter = SatelliteRecyclerAdapter(this, satelliteCollection)
binding.recyclerView.adapter = satelliteAdapter
- binding.recyclerView.addItemDecoration(RecyclerViewItemDivider(1, Color.WHITE))
+ binding.recyclerView.addItemDecoration(RecyclerViewItemDivider(0f, 0f, Color.WHITE))
//高德定位
locationKit.getCurrentLocation(false, object : OnGetLocationListener {
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt
index c7c8bb9..5417e1f 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt
@@ -1,9 +1,5 @@
package com.casic.common.detector.gd.view
-import android.content.ComponentName
-import android.content.Context
-import android.content.Intent
-import android.content.ServiceConnection
import android.graphics.Color
import android.hardware.Sensor
import android.hardware.SensorEvent
@@ -13,9 +9,6 @@
import android.media.SoundPool
import android.os.Bundle
import android.os.CountDownTimer
-import android.os.Handler
-import android.os.IBinder
-import android.os.Message
import android.util.Log
import android.view.View
import android.view.WindowManager
@@ -25,28 +18,25 @@
import com.amap.api.maps.AMapUtils
import com.amap.api.maps.model.LatLng
import com.casic.common.detector.gd.R
+import com.casic.common.detector.gd.base.SerialPortActivity
import com.casic.common.detector.gd.callback.OnGetLocationListener
import com.casic.common.detector.gd.databinding.ActivitySearchMarkerBinding
import com.casic.common.detector.gd.extensions.toBuryDepth
import com.casic.common.detector.gd.extensions.toMarkerId
import com.casic.common.detector.gd.extensions.toSignalStrength
import com.casic.common.detector.gd.model.MarkerDistanceData
-import com.casic.common.detector.gd.service.SerialPortService
import com.casic.common.detector.gd.utils.CurrentSegment
import com.casic.common.detector.gd.utils.DataBaseManager
import com.casic.common.detector.gd.utils.LocaleConstant
import com.casic.common.detector.gd.utils.LocationKit
-import com.casic.common.detector.gd.utils.RuntimeCache
import com.casic.common.detector.gd.vm.TaskViewModel
import com.casic.common.detector.gd.widgets.RadarScanView
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.getSystemService
import com.pengxh.kt.lite.extensions.navigatePageTo
import com.pengxh.kt.lite.extensions.show
import com.pengxh.kt.lite.utils.LiteKitConstant
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.utils.SaveKeyValues
-import com.pengxh.kt.lite.utils.WeakReferenceHandler
import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -55,8 +45,8 @@
import java.util.TimerTask
import kotlin.math.atan2
-class SearchMarkerActivity : KotlinBaseActivity(),
- SensorEventListener, Handler.Callback {
+class SearchMarkerActivity : SerialPortActivity(),
+ SensorEventListener {
private val kTag = "SearchMarkerActivity"
private val context = this
@@ -76,38 +66,10 @@
private var signalEnergy = 0 //标识器信号强度
private var gravity: FloatArray? = null
private var geomagnetic: FloatArray? = null
- private var serialPortService: SerialPortService? = null
- private lateinit var searchSignalEnergyTimer: Timer
-
- private val serviceConnection = object : ServiceConnection {
- override fun onServiceConnected(name: ComponentName?, iBinder: IBinder?) {
- if (name != null && iBinder != null && iBinder is SerialPortService.ServiceBinder) {
- try {
- serialPortService = iBinder.getSerialPortService()
- Log.d(kTag, "onServiceConnected: 服务已绑定,开始搜索标识器")
- searchMarker()
- } catch (e: Exception) {
- Log.e(kTag, "onServiceConnected: 绑定服务时发生异常", e)
- }
- } else {
- Log.w(kTag, "onServiceConnected: name 或 iBinder 为 null")
- }
- }
-
- override fun onServiceDisconnected(name: ComponentName?) {
-
- }
- }
-
- companion object {
- var weakReferenceHandler: WeakReferenceHandler? = null
- }
override fun initOnCreate(savedInstanceState: Bundle?) {
- weakReferenceHandler = WeakReferenceHandler(this)
-
- val flag = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY) as String
- isExecuteTask = flag != "0"
+ val taskState = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY) as String
+ isExecuteTask = taskState != "0"
slowSoundResourceId = soundPool.load(this, R.raw.ring4, 1)
fastSoundResourceId = soundPool.load(this, R.raw.ring2, 1)
@@ -131,14 +93,11 @@
binding.taskStateView.isSelected = true
}
- //绑定串口通信服务
- Intent(this, SerialPortService::class.java).also {
- bindService(it, serviceConnection, Context.BIND_AUTO_CREATE)
- }
+ openSerialPort()
+ searchMarker(CurrentSegment.SearchMarker)
//在标识器信号强度很强的时候,从数据库中计算出距离最近的点,以防出现探测不到ID的情况
- searchSignalEnergyTimer = Timer()
- searchSignalEnergyTimer.schedule(object : TimerTask() {
+ Timer().schedule(object : TimerTask() {
override fun run() {
if (signalEnergy <= 700) {//18°
runOnUiThread {
@@ -183,21 +142,8 @@
}, 0, 2000)
}
- private val countDownTimer = object : CountDownTimer(10 * 1000, 1000) {
- override fun onTick(millisUntilFinished: Long) {
-
- }
-
- override fun onFinish() {
- LoadingDialog.dismiss()
- "标识器深度探测超时,请移动位置重试".show(context)
- searchMarker()
- }
- }
-
override fun initEvent() {
binding.depthButton.setOnClickListener {
- soundPool.autoPause()
val result = DataBaseManager.get.queryMarkerById(markerId)
if (result.isNotEmpty()) {
val tag = when (result.first().markerType) {
@@ -208,18 +154,25 @@
}
if (tag == '1') {
"此标识器无法读取埋深!".show(this)
- searchMarker()
} else {
+ soundPool.autoPause()
LoadingDialog.show(this, "正在探测标识器埋深,请稍后...")
- countDownTimer.start()
// 发送读取标识器埋设深度指令
- RuntimeCache.currentSegment = CurrentSegment.DetectMarkerDepth
- serialPortService?.writeCommand(tag)
+ detectDepth(tag)
+ object : CountDownTimer(3 * 1000, 1000) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ LoadingDialog.dismiss()
+ updateSegment(CurrentSegment.SearchMarker)
+ }
+ }.start()
}
} else {
LoadingDialog.dismiss()
"标识器未安装,安装成功后才可读取埋深!".show(this)
- searchMarker()
}
}
@@ -236,13 +189,11 @@
}
}
- override fun handleMessage(msg: Message): Boolean {
- val buffer = msg.obj as ByteArray
- if (msg.what == LocaleConstant.DETECT_MARKER_DEPTH) {
- val tag = (buffer.first().toInt() and 0xFF).toString(16).uppercase()
- if (tag == "53") {
+ override fun onDataReceived(buffer: ByteArray, segment: CurrentSegment) {
+ if (segment == CurrentSegment.DetectDepth) {
+ val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase()
+ if (flag == "53" && buffer.size == 5) {
LoadingDialog.dismiss()
- countDownTimer.cancel()
try {
AlertMessageDialog.Builder().setContext(context)
.setTitle("温馨提示")
@@ -251,54 +202,32 @@
.setOnDialogButtonClickListener(object :
AlertMessageDialog.OnDialogButtonClickListener {
override fun onConfirmClick() {
- searchMarker()
+ updateSegment(CurrentSegment.SearchMarker)
}
}).build().show()
} catch (e: WindowManager.BadTokenException) {
e.printStackTrace()
- } catch (e: NumberFormatException) {
- e.printStackTrace()
}
}
- } else if (msg.what == LocaleConstant.SEARCH_MARKER) {
- try {
- // 读取到信号强度
- when ((buffer.first().toInt() and 0xFF).toString(16).uppercase()) {
- "4E" -> {
- val signalEnergy = buffer.toSignalStrength()
+ } else if (segment == CurrentSegment.SearchMarker) {
+ val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase()
+ if (flag == "30" && buffer.size == 10) {
+ handleMarker(buffer.toMarkerId())
+ } else if (flag == "4E" && buffer.size == 5) {
+ val signalEnergy = buffer.toSignalStrength()
- //声音
- updateSound(signalEnergy)
+ //声音
+ updateSound(signalEnergy)
- //信号强度显示
- updateProgressBar(signalEnergy)
+ //信号强度显示
+ updateProgressBar(signalEnergy)
- //搜索信号文字显示
- updateTextResult(signalEnergy)
- }
-
- "30" -> {
- handleMarker(buffer.toMarkerId())
- }
-
- else -> {
- Log.d(kTag, "乱码数据: ${buffer.contentToString()}")
- }
- }
- } catch (e: Exception) {
- e.printStackTrace()
- Log.e(kTag, "Error processing buffer data", e)
+ //搜索信号文字显示
+ updateTextResult(signalEnergy)
+ } else {
+ Log.d(kTag, "乱码数据: ${buffer.contentToString()}")
}
}
- return true
- }
-
- /**
- * 搜索标识器
- * */
- private fun searchMarker() {
- RuntimeCache.currentSegment = CurrentSegment.SearchMarker
- serialPortService?.writeCommand('2', '6')
}
private fun updateSound(signalEnergy: Int) {
@@ -492,9 +421,8 @@
override fun onDestroy() {
super.onDestroy()
+ closeSerialPort()
soundPool.autoPause()
- RuntimeCache.currentSegment = null
locationKit.stopLocation()
- unbindService(serviceConnection)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/VersionControlActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/VersionControlActivity.kt
index ddc5a32..8641c79 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/VersionControlActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/VersionControlActivity.kt
@@ -13,17 +13,17 @@
import com.casic.common.detector.gd.databinding.ActivityVersionControlBinding
import com.casic.common.detector.gd.extensions.appendDownloadUrl
import com.casic.common.detector.gd.extensions.initImmersionBar
-import com.casic.common.detector.gd.utils.FileDownloadManager
import com.casic.common.detector.gd.utils.FileType
import com.casic.common.detector.gd.vm.VersionViewModel
-import com.casic.common.detector.gd.widgets.ProgressDialog
import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.createDownloadFileDir
import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.FileDownloadManager
import com.pengxh.kt.lite.utils.LoadState
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.widget.TitleBarView
import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.ProgressDialog
import java.io.File
class VersionControlActivity : KotlinBaseActivity() {
@@ -118,7 +118,7 @@
installApk(file)
}
- override fun onFailed(t: Throwable) {
+ override fun onDownloadFailed(t: Throwable) {
t.printStackTrace()
progressDialog.dismiss()
}
diff --git a/app/src/main/java/com/casic/common/detector/gd/widgets/ProgressDialog.kt b/app/src/main/java/com/casic/common/detector/gd/widgets/ProgressDialog.kt
deleted file mode 100644
index af480b0..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/widgets/ProgressDialog.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.casic.common.detector.gd.widgets
-
-import android.app.Dialog
-import android.content.Context
-import android.os.Bundle
-import com.casic.common.detector.gd.databinding.DialogProgressBinding
-import com.pengxh.kt.lite.R
-import com.pengxh.kt.lite.extensions.binding
-import com.pengxh.kt.lite.extensions.initDialogLayoutParams
-
-class ProgressDialog(context: Context) : Dialog(context, R.style.UserDefinedDialogStyle) {
-
- private val binding: DialogProgressBinding by binding()
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- this.initDialogLayoutParams(0.5f)
- setCanceledOnTouchOutside(false)
- setCancelable(false)
- binding.progressBar.progress = 0
- binding.progressText.text = "0 %"
- }
-
- fun setMaxProgress(maxProgress: Long) {
- binding.progressBar.max = maxProgress.toInt()
- }
-
- private fun getMaxProgress() = binding.progressBar.max
-
- fun updateProgress(progress: Long) {
- binding.progressBar.progress = progress.toInt()
-
- val percent = (progress.toFloat() / getMaxProgress()) * 100
- binding.progressText.text = String.format("%.2f %%", percent)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_version_control.xml b/app/src/main/res/layout/activity_version_control.xml
index 887248f..15f3a91 100644
--- a/app/src/main/res/layout/activity_version_control.xml
+++ b/app/src/main/res/layout/activity_version_control.xml
@@ -81,7 +81,6 @@
-
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
index 6cb496c..e5fe1f5 100644
--- a/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt
@@ -1,6 +1,7 @@
package com.casic.common.detector.gd.base
import android.app.Application
+import android.util.Log
import com.casic.common.detector.gd.greendao.DaoMaster
import com.casic.common.detector.gd.greendao.DaoSession
import com.casic.common.detector.gd.uart.SerialPort
@@ -52,6 +53,7 @@
//千寻报文数据下发串口号
add(SerialPort(File("/dev/ttyS1"), 9600, 0))
}
+ Log.d(kTag, "onCreate: 已初始化 ${serialPorts.size} 个串口")
} catch (e: SecurityException) {
"您没有串口的读写权限!".show(this)
} catch (e: IOException) {
diff --git a/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
new file mode 100644
index 0000000..08b3e19
--- /dev/null
+++ b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt
@@ -0,0 +1,204 @@
+package com.casic.common.detector.gd.base
+
+import android.os.Bundle
+import android.os.Handler
+import android.os.Message
+import android.util.Log
+import androidx.appcompat.app.AppCompatActivity
+import androidx.viewbinding.ViewBinding
+import com.casic.common.detector.gd.utils.CurrentSegment
+import com.casic.common.detector.gd.utils.GpioManager
+import com.pengxh.kt.lite.utils.WeakReferenceHandler
+import java.io.IOException
+import java.util.Timer
+import java.util.TimerTask
+import java.util.concurrent.atomic.AtomicInteger
+
+abstract class SerialPortActivity : AppCompatActivity(), Handler.Callback {
+
+ private val kTag = "SerialPortActivity"
+ private val taskTimer by lazy { Timer() }
+ private val weakReferenceHandler by lazy { WeakReferenceHandler(this) }
+
+ //输出流
+ private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
+
+ //输入流
+ private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
+ private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
+
+ private var segment: CurrentSegment? = null
+
+ protected lateinit var binding: VB
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = initViewBinding()
+ setContentView(binding.root)
+ setupTopBarLayout()
+ initOnCreate(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = firstInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+
+ Thread {
+ val buffer = ByteArray(128)
+ try {
+ while (!Thread.interrupted()) {
+ val bytesRead = lastInStream.read(buffer)
+ if (bytesRead > 0) {
+ weakReferenceHandler.let {
+ val message = it.obtainMessage()
+ message.what = 2025012001
+ message.obj = buffer.copyOf(bytesRead)
+ it.sendMessage(message)
+ }
+ }
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }.start()
+ }
+
+ /**
+ * 初始化ViewBinding
+ */
+ abstract fun initViewBinding(): VB
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initOnCreate(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ abstract fun onDataReceived(buffer: ByteArray, segment: CurrentSegment)
+
+ override fun handleMessage(msg: Message): Boolean {
+ if (msg.what == 2025012001) {
+ val bytes = msg.obj as ByteArray
+ if (segment == null) {
+ return true
+ }
+ Log.d(kTag, "$segment - ${bytes.contentToString()}")
+ onDataReceived(bytes, segment!!)
+ }
+ return true
+ }
+
+ private var readMarkerIdTask: TimerTask? = null
+ private var searchMarkerTask: TimerTask? = null
+
+ fun readMarkerId() {
+ this.segment = CurrentSegment.InstallMarker
+ readMarkerIdTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(readMarkerIdTask, 0, 300)
+ }
+
+ fun detectDepth(tag: Char) {
+ this.segment = CurrentSegment.DetectDepth
+ outStream.write('3'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write(tag.code)
+ outStream.flush()
+ }
+
+ fun updateSegment(segment: CurrentSegment) {
+ this.segment = segment
+ }
+
+ fun searchMarker(segment: CurrentSegment) {
+ this.segment = segment
+ searchMarkerTask = object : TimerTask() {
+ override fun run() {
+ outStream.write('2'.code)
+ outStream.flush()
+
+ Thread.sleep(50)
+
+ outStream.write('6'.code)
+ outStream.flush()
+ }
+ }
+ taskTimer.schedule(searchMarkerTask, 0, 300)
+ }
+
+ /***************************************************************************************/
+ private val gpioManager by lazy { GpioManager() }
+
+ /**
+ * 读取数据 1
+ * 暂停读取 0
+ * */
+ private val gpioState = AtomicInteger(0)
+ fun openSerialPort() {
+ if (gpioState.get() != 1) {
+ gpioManager.setGpioHigh("18")
+ gpioState.set(1)
+ Log.d(kTag, "openSerialPort: 调高串口电位")
+ } else {
+ Log.d(kTag, "openSerialPort: 已经是高电位,直接读数据")
+ }
+ }
+
+ fun closeSerialPort() {
+ if (segment != null) {
+ segment = null
+ }
+ readMarkerIdTask?.cancel()
+ searchMarkerTask?.cancel()
+ if (gpioState.get() == 0) {
+ Log.d(kTag, "closeSerialPort: 已经是低电位,不响应")
+ return
+ }
+ // 降低串口电位
+ gpioManager.setGpioLow("18")
+ gpioState.set(0)
+ Log.d(kTag, "closeSerialPort: 降低串口电位")
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ closeSerialPort()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
index 442189e..5c3ee01 100644
--- a/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/extensions/ByteArray.kt
@@ -1,42 +1,20 @@
package com.casic.common.detector.gd.extensions
-import android.util.Log
-
/**
* 因为数据频率很高,而且每一帧数据至少有一个信号值,如果有多个信号强度值,取平均值
*
* [78, 53, 49, 55, 51]
*
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
- * [78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51, 78, 53, 49, 55, 51]
- *
* */
fun ByteArray.toSignalStrength(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var strength = 0
+ for (byte in dataBytes) {
+ strength = strength * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return strength
}
/**
@@ -44,32 +22,13 @@
*
* [48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
*
- * [48, 48, 48, 56, 56, 57, 49, 48, 55, 51, 48, 48, 48, 56, 56, 57, 49, 48, 55, 51]
- *
* */
fun ByteArray.toMarkerId(): String {
- //判断数据合理性
- val validBytes = if (this.size % 10 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 10) * 10
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ val id = this.map { it.toInt().toChar() }.joinToString("")
+ if (id.matches("-?\\d+".toRegex())) {
+ return id
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 10) {
- // 每10个字节取一次数据转为ASCII
- val tempBytes = validBytes.sliceArray(i until minOf(i + 10, validBytes.size))
- val string = tempBytes.map { it.toInt().toChar() }.joinToString("")
- if (string.matches("-?\\d+".toRegex())) {
- list.add(string)
- } else {
- Log.d("kTag", "toDeviceCode: 编号解析失败")
- }
- }
- return list.last()
+ return ""
}
/**
@@ -77,31 +36,14 @@
*
* [83, 48, 48, 48, 57]
*
- * [83, 48, 48, 48, 57, 83, 48, 48, 48, 57]
* */
fun ByteArray.toBuryDepth(): Int {
- //判断数据合理性
- val validBytes = if (this.size % 5 == 0) {
- this
- } else {
- // 计算最大能取到的5的倍数的数据长度
- val maxMultipleOfFour = (this.size / 5) * 5
- // 获取最大能取到的5的倍数的数据
- this.sliceArray(0 until maxMultipleOfFour)
+ // [78, 53, 49, 55, 51]
+ // 第一个字节是标志位,丢弃,将后面的数据转为十进制
+ val dataBytes = this.sliceArray(1 until this.size)
+ var depth = 0
+ for (byte in dataBytes) {
+ depth = depth * 10 + (byte - '0'.code.toByte())
}
-
- val list = ArrayList()
- for (i in validBytes.indices step 5) {
- // 每5个字节取一次数据
- val tempBytes = validBytes.sliceArray(i until minOf(i + 5, validBytes.size))
- // [78, 53, 49, 55, 51]
- // 第一个字节是标志位,丢弃,将后面的数据转为十进制
- val dataBytes = tempBytes.sliceArray(1 until tempBytes.size)
- var decimalValue = 0
- for (byte in dataBytes) {
- decimalValue = decimalValue * 10 + (byte - '0'.code.toByte())
- }
- list.add(decimalValue)
- }
- return list.average().toInt()
+ return depth
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt b/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
deleted file mode 100644
index 76cf583..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/service/SerialPortService.kt
+++ /dev/null
@@ -1,136 +0,0 @@
-package com.casic.common.detector.gd.service
-
-import android.app.Service
-import android.content.Intent
-import android.os.Binder
-import android.os.IBinder
-import android.util.Log
-import com.casic.common.detector.gd.base.BaseApplication
-import com.casic.common.detector.gd.utils.CurrentSegment
-import com.casic.common.detector.gd.utils.LocaleConstant
-import com.casic.common.detector.gd.utils.RuntimeCache
-import com.casic.common.detector.gd.view.InstallMarkerActivity
-import com.casic.common.detector.gd.view.MainActivity
-import com.casic.common.detector.gd.view.SearchMarkerActivity
-import java.io.IOException
-import java.io.InputStream
-import java.util.concurrent.Executors
-import java.util.concurrent.TimeUnit
-
-class SerialPortService : Service() {
-
- private val kTag = "SerialPortService"
- private val sendExecutor = Executors.newFixedThreadPool(5)
- private val readExecutor = Executors.newSingleThreadScheduledExecutor()
-
- //输出流
- private val outStream by lazy { BaseApplication.get().getSerialPorts().first().outputStream }
-
- //输入流
- private val firstInStream by lazy { BaseApplication.get().getSerialPorts().first().inputStream }
- private val lastInStream by lazy { BaseApplication.get().getSerialPorts().last().inputStream }
-
- override fun onCreate() {
- super.onCreate()
- try {
- // 使用单线程调度器读取数据
- readExecutor.scheduleAtFixedRate({
- readData(firstInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
-
- readExecutor.scheduleAtFixedRate({
- readData(lastInStream)
- }, 100, 150, TimeUnit.MILLISECONDS)
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- private fun readData(inputStream: InputStream) {
- try {
- val buffer = ByteArray(1024)
- var bytesRead: Int
- while (inputStream.available() > 0) {
- bytesRead = inputStream.read(buffer)
- if (bytesRead > 0) {
- when (RuntimeCache.currentSegment) {
- CurrentSegment.DetectMarkerDepth -> {
- //深度
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.DETECT_MARKER_DEPTH
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.InstallMarker -> {
- //安装点
- InstallMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.INSTALL_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.FreeInspection -> {
- //自由巡检
- MainActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.FREE_INSPECTION
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- CurrentSegment.SearchMarker -> {
- //搜索标识器
- SearchMarkerActivity.weakReferenceHandler?.apply {
- val message = obtainMessage()
- message.what = LocaleConstant.SEARCH_MARKER
- message.obj = buffer.copyOf(bytesRead)
- sendMessage(message)
- }
- }
-
- else -> {
- val bytes = buffer.copyOf(bytesRead)
- Log.d(kTag, "空状态,不处理 ===> ${bytes.contentToString()}")
- }
- }
- }
- }
- } catch (e: IOException) {
- e.printStackTrace()
- }
- }
-
- fun writeCommand(vararg command: Char) {
- Log.d(kTag, "writeCommand: ${command.contentToString()}")
- if (command.size == 1) {
- sendExecutor.submit {
- outStream.write(command.first().code)
- outStream.flush()
- }
- } else {
- command.forEach {
- sendExecutor.submit {
- outStream.write(it.code)
- outStream.flush()
- }
- Thread.sleep(1000)
- }
- }
- }
-
- override fun onBind(intent: Intent?): IBinder {
- return ServiceBinder()
- }
-
- inner class ServiceBinder : Binder() {
- fun getSerialPortService(): SerialPortService {
- return this@SerialPortService
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt b/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
index 0606b72..9efa097 100644
--- a/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/utils/CurrentSegment.kt
@@ -1,23 +1,23 @@
package com.casic.common.detector.gd.utils
-sealed class CurrentSegment {
+enum class CurrentSegment {
/**
* 安装标识器
* */
- object InstallMarker : CurrentSegment()
+ InstallMarker,
/**
* 自由巡检
* */
- object FreeInspection : CurrentSegment()
+ FreeInspection,
/**
* 搜索标识器
* */
- object SearchMarker : CurrentSegment()
+ SearchMarker,
/**
* 探测标识器深度
* */
- object DetectMarkerDepth : CurrentSegment()
+ DetectDepth
}
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt b/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt
deleted file mode 100644
index c9151a8..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/utils/FileDownloadManager.kt
+++ /dev/null
@@ -1,150 +0,0 @@
-package com.casic.common.detector.gd.utils
-
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.SupervisorJob
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import okhttp3.Call
-import okhttp3.Callback
-import okhttp3.OkHttpClient
-import okhttp3.Request
-import okhttp3.Response
-import java.io.File
-import java.io.IOException
-import java.util.concurrent.atomic.AtomicBoolean
-
-class FileDownloadManager(builder: Builder) {
-
- private val httpClient by lazy { OkHttpClient() }
-
- class Builder {
- lateinit var url: String
- lateinit var suffix: String
- lateinit var directory: File
- lateinit var downloadListener: OnFileDownloadListener
-
- /**
- * 文件下载地址
- * */
- fun setDownloadFileSource(url: String): Builder {
- this.url = url
- return this
- }
-
- /**
- * 文件后缀
- * 如:apk等
- * */
- fun setFileSuffix(suffix: String): Builder {
- this.suffix = if (suffix.contains(".")) {
- //去掉前缀的点
- suffix.drop(1)
- } else {
- suffix
- }
- return this
- }
-
- /**
- * 文件保存的地址
- * */
- fun setFileSaveDirectory(directory: File): Builder {
- this.directory = directory
- return this
- }
-
- /**
- * 设置文件下载回调监听
- * */
- fun setOnFileDownloadListener(downloadListener: OnFileDownloadListener): Builder {
- this.downloadListener = downloadListener
- return this
- }
-
- fun build(): FileDownloadManager {
- if (!::url.isInitialized || !::suffix.isInitialized || !::directory.isInitialized || !::downloadListener.isInitialized) {
- throw IllegalStateException("All properties must be initialized before building.")
- }
- return FileDownloadManager(this)
- }
- }
-
- private val url = builder.url
- private val suffix = builder.suffix
- private val directory = builder.directory
- private val listener = builder.downloadListener
-
- /**
- * 开始下载
- * */
- fun start() {
- val job = SupervisorJob()
- val scope = CoroutineScope(Dispatchers.Main + job)
-
- val request = Request.Builder().get().url(url).build()
- val newCall = httpClient.newCall(request)
- val isExecuting = AtomicBoolean(false)
-
- /**
- * 如果已被加入下载队列,则取消之前的,重新下载
- */
- if (isExecuting.getAndSet(true)) {
- newCall.cancel()
- }
-
- //异步下载文件
- newCall.enqueue(object : Callback {
- override fun onFailure(call: Call, e: IOException) {
- scope.launch(Dispatchers.Main) {
- listener.onFailed(e)
- }
- }
-
- override fun onResponse(call: Call, response: Response) {
- scope.launch(Dispatchers.IO) {
- val body = response.body
- if (body == null) {
- listener.onFailed(IOException("Response body is null"))
- throw IOException("Response body is null")
- } else {
- val inputStream = body.byteStream()
- val fileSize = body.contentLength()
-
- if (fileSize <= 0) {
- throw IllegalArgumentException("Invalid file size")
- }
- listener.onDownloadStart(fileSize)
-
- val file = File(directory, "${System.currentTimeMillis()}.${suffix}")
- file.outputStream().use { fos ->
- val buffer = ByteArray(2048)
- var sum = 0L
- var read: Int
- while (inputStream.read(buffer).also { read = it } != -1) {
- fos.write(buffer, 0, read)
- sum += read.toLong()
- withContext(Dispatchers.Main) {
- listener.onProgressChanged(sum)
- }
- }
- }
-
- withContext(Dispatchers.Main) {
- listener.onDownloadEnd(file)
- }
-
- job.cancel()
- }
- }
- }
- })
- }
-
- interface OnFileDownloadListener {
- fun onDownloadStart(total: Long)
- fun onProgressChanged(progress: Long)
- fun onDownloadEnd(file: File)
- fun onFailed(t: Throwable)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt b/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
index 2334680..c658924 100644
--- a/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/utils/LocaleConstant.kt
@@ -14,10 +14,6 @@
const val PERMISSIONS_CODE = 999
const val MAX_DISTANCE = 5.5f //表盘最大显示距离
- const val FREE_INSPECTION = 20250101
- const val INSTALL_MARKER = 20250102
- const val DETECT_MARKER_DEPTH = 20250103
- const val SEARCH_MARKER = 20250104
const val AUTO_SAVE = "AUTO_SAVE"
const val USER_ACCOUNT = "USER_ACCOUNT"
diff --git a/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt b/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt
deleted file mode 100644
index 104f971..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.casic.common.detector.gd.utils
-
-object RuntimeCache {
- var currentSegment: CurrentSegment? = null
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt
index c5f18a6..b3dce3c 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt
@@ -1,26 +1,19 @@
package com.casic.common.detector.gd.view
import android.app.DatePickerDialog
-import android.content.ComponentName
-import android.content.Context
import android.content.DialogInterface
-import android.content.Intent
-import android.content.ServiceConnection
import android.hardware.Camera
import android.media.AudioAttributes
import android.media.SoundPool
import android.os.Bundle
import android.os.CountDownTimer
-import android.os.Handler
-import android.os.IBinder
-import android.os.Message
-import android.util.Log
import android.view.View
import android.widget.AdapterView
import androidx.lifecycle.ViewModelProvider
import com.amap.api.location.AMapLocation
import com.casic.common.detector.gd.R
import com.casic.common.detector.gd.adapter.EditableImageAdapter
+import com.casic.common.detector.gd.base.SerialPortActivity
import com.casic.common.detector.gd.bean.MarkerLocalBean
import com.casic.common.detector.gd.callback.OnGetLocationListener
import com.casic.common.detector.gd.callback.OnImageCompressListener
@@ -33,18 +26,15 @@
import com.casic.common.detector.gd.extensions.toColor
import com.casic.common.detector.gd.extensions.toMarkerId
import com.casic.common.detector.gd.extensions.toObjectType
-import com.casic.common.detector.gd.service.SerialPortService
import com.casic.common.detector.gd.utils.CurrentSegment
import com.casic.common.detector.gd.utils.DataBaseManager
import com.casic.common.detector.gd.utils.LocaleConstant
import com.casic.common.detector.gd.utils.LocationKit
-import com.casic.common.detector.gd.utils.RuntimeCache
import com.casic.common.detector.gd.vm.TaskViewModel
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.appendZero
import com.pengxh.kt.lite.extensions.dateToTimestamp
import com.pengxh.kt.lite.extensions.navigatePageTo
@@ -55,13 +45,12 @@
import com.pengxh.kt.lite.utils.LoadState
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.utils.SaveKeyValues
-import com.pengxh.kt.lite.utils.WeakReferenceHandler
import com.pengxh.kt.lite.widget.TitleBarView
import java.io.File
import java.util.Calendar
import java.util.Date
-class InstallMarkerActivity : KotlinBaseActivity(), Handler.Callback {
+class InstallMarkerActivity : SerialPortActivity() {
private val kTag = "InstallMarkerActivity"
private val context = this
@@ -73,7 +62,6 @@
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build()
private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build()
private var soundResourceId = 0
- private var serialPortService: SerialPortService? = null
private lateinit var imageAdapter: EditableImageAdapter
override fun initEvent() {
@@ -255,18 +243,18 @@
//读标识器
binding.readMarkerButton.setOnClickListener {
+ openSerialPort()
LoadingDialog.show(this, "标识器读取中,请稍后...")
countDownTimer.start()
binding.readMarkerButton.isEnabled = false
- RuntimeCache.currentSegment = CurrentSegment.InstallMarker
- serialPortService?.writeCommand('2')
+ readMarkerId()
}
}
- override fun handleMessage(msg: Message): Boolean {
- if (msg.what == LocaleConstant.INSTALL_MARKER) {
- val buffer = msg.obj as ByteArray
- if ((buffer.first().toInt() and 0xFF).toString(16).uppercase() == "30") {
+ override fun onDataReceived(buffer: ByteArray, segment: CurrentSegment) {
+ if (segment == CurrentSegment.InstallMarker) {
+ val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase()
+ if (flag == "30" && buffer.size == 10) {
val markerId = buffer.toMarkerId()
LoadingDialog.dismiss()
countDownTimer.cancel()
@@ -274,7 +262,6 @@
binding.identifierInclude.identifierIdView.text = markerId
}
}
- return true
}
/**
@@ -363,37 +350,7 @@
})
}
- private val serviceConnection = object : ServiceConnection {
- override fun onServiceConnected(name: ComponentName?, iBinder: IBinder?) {
- if (name != null && iBinder != null && iBinder is SerialPortService.ServiceBinder) {
- try {
- serialPortService = iBinder.getSerialPortService()
- Log.d(kTag, "onServiceConnected: 服务已绑定")
- } catch (e: Exception) {
- Log.e(kTag, "onServiceConnected: 绑定服务时发生异常", e)
- }
- } else {
- Log.w(kTag, "onServiceConnected: name 或 iBinder 为 null")
- }
- }
-
- override fun onServiceDisconnected(name: ComponentName?) {
- //在连接正常关闭的情况下不会被调用, 只在Service被破坏了或者被杀死的时候调用
- }
- }
-
- companion object {
- var weakReferenceHandler: WeakReferenceHandler? = null
- }
-
override fun initOnCreate(savedInstanceState: Bundle?) {
- weakReferenceHandler = WeakReferenceHandler(this)
-
- //绑定串口通信服务
- Intent(this, SerialPortService::class.java).also {
- bindService(it, serviceConnection, Context.BIND_AUTO_CREATE)
- }
-
locationKit.getCurrentLocation(true, object : OnGetLocationListener {
override fun onSuccess(location: AMapLocation) {
binding.identifierInclude.lngView.text = location.longitude.toString()
@@ -552,8 +509,6 @@
override fun onDestroy() {
super.onDestroy()
- RuntimeCache.currentSegment = null
locationKit.stopLocation()
- unbindService(serviceConnection)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt
index 8a798b6..2c48cc9 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt
@@ -1,18 +1,12 @@
package com.casic.common.detector.gd.view
import android.app.Activity
-import android.content.ComponentName
-import android.content.Context
import android.content.Intent
-import android.content.ServiceConnection
import android.graphics.BitmapFactory
import android.graphics.Color
import android.media.AudioAttributes
import android.media.SoundPool
import android.os.Bundle
-import android.os.Handler
-import android.os.IBinder
-import android.os.Message
import android.util.Log
import android.view.KeyEvent
import android.view.View
@@ -34,6 +28,7 @@
import com.amap.api.maps.model.MyLocationStyle
import com.casic.common.detector.gd.R
import com.casic.common.detector.gd.base.BaseApplication
+import com.casic.common.detector.gd.base.SerialPortActivity
import com.casic.common.detector.gd.bean.MarkerLocalBean
import com.casic.common.detector.gd.bean.TaskLocalBean
import com.casic.common.detector.gd.callback.OnGetAddressListener
@@ -47,32 +42,27 @@
import com.casic.common.detector.gd.model.TaskDetailLocalModel
import com.casic.common.detector.gd.model.TaskModel
import com.casic.common.detector.gd.service.NtripConnectService
-import com.casic.common.detector.gd.service.SerialPortService
import com.casic.common.detector.gd.utils.CurrentSegment
import com.casic.common.detector.gd.utils.DataBaseManager
import com.casic.common.detector.gd.utils.ExcelKit
-import com.casic.common.detector.gd.utils.FileDownloadManager
import com.casic.common.detector.gd.utils.FileType
-import com.casic.common.detector.gd.utils.GpioManager
import com.casic.common.detector.gd.utils.LocaleConstant
import com.casic.common.detector.gd.utils.LocationKit
import com.casic.common.detector.gd.utils.RouteOnMap
-import com.casic.common.detector.gd.utils.RuntimeCache
import com.casic.common.detector.gd.vm.TaskViewModel
import com.casic.common.detector.gd.widgets.MarkerDetailDialog
import com.casic.common.detector.gd.widgets.QueryMarkerDialog
import com.casic.common.detector.gd.widgets.SamplePopupWindow
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.createDownloadFileDir
import com.pengxh.kt.lite.extensions.dp2px
import com.pengxh.kt.lite.extensions.isNetworkConnected
import com.pengxh.kt.lite.extensions.navigatePageTo
import com.pengxh.kt.lite.extensions.show
import com.pengxh.kt.lite.extensions.timestampToCompleteDate
+import com.pengxh.kt.lite.utils.FileDownloadManager
import com.pengxh.kt.lite.utils.LoadState
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.utils.SaveKeyValues
-import com.pengxh.kt.lite.utils.WeakReferenceHandler
import com.pengxh.kt.lite.widget.TitleBarView
import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
import com.pengxh.kt.lite.widget.dialog.AlertInputDialog
@@ -82,45 +72,13 @@
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
-import java.util.concurrent.atomic.AtomicInteger
-class MainActivity : KotlinBaseActivity(), AMap.OnMarkerClickListener,
- OnMapLongClickListener, Handler.Callback {
+class MainActivity : SerialPortActivity(), AMap.OnMarkerClickListener,
+ OnMapLongClickListener {
private val kTag = "MainActivity"
private val context = this
-
- /***************************************************************************************/
- private val gpioManager by lazy { GpioManager() }
-
- /**
- * 读取数据 1
- * 暂停读取 0
- * */
- private val gpioState = AtomicInteger(0)
- private fun openSerialPort() {
- if (gpioState.get() != 1) {
- gpioManager.setGpioHigh("18")
- gpioState.set(1)
- Log.d(kTag, "openSerialPort: 调高串口电位")
- } else {
- Log.d(kTag, "openSerialPort: 已经是高电位,直接读数据")
- }
- }
-
- private fun closeSerialPort() {
- if (gpioState.get() == 0) {
- Log.d(kTag, "closeSerialPort: 已经是低电位,直接返回")
- return
- }
- // 降低串口电位
- gpioManager.setGpioLow("18")
- gpioState.set(0)
- Log.d(kTag, "closeSerialPort: 降低串口电位")
- }
-
- /***************************************************************************************/
private val samplePopupWindow by lazy { SamplePopupWindow(this) }
private val detailDialog by lazy { MarkerDetailDialog(this) }
private val locationKit by lazy { LocationKit(this) }
@@ -133,7 +91,6 @@
private var freeTaskTitle = ""
private var ids = HashSet()
private var freeTaskId: String? = null
- private var serialPortService: SerialPortService? = null
private var soundResourceId = 0
private var isExecuteTask = false
private lateinit var aMap: AMap
@@ -146,43 +103,13 @@
binding.rootView.initImmersionBar(this, false, R.color.themeColor)
}
- private val serviceConnection = object : ServiceConnection {
- override fun onServiceConnected(name: ComponentName?, iBinder: IBinder?) {
- if (name != null && iBinder != null && iBinder is SerialPortService.ServiceBinder) {
- try {
- serialPortService = iBinder.getSerialPortService()
- Log.d(kTag, "onServiceConnected: 服务已绑定")
- openSerialPort()
- } catch (e: Exception) {
- Log.e(kTag, "onServiceConnected: 绑定服务时发生异常", e)
- }
- } else {
- Log.w(kTag, "onServiceConnected: name 或 iBinder 为 null")
- }
- }
-
- override fun onServiceDisconnected(name: ComponentName?) {
-
- }
- }
-
- companion object {
- var weakReferenceHandler: WeakReferenceHandler? = null
- }
-
override fun initOnCreate(savedInstanceState: Bundle?) {
- weakReferenceHandler = WeakReferenceHandler(this)
-
//地图初始化
initMapConfig(savedInstanceState)
- //绑定串口通信服务
- Intent(this, SerialPortService::class.java).also {
- bindService(it, serviceConnection, Context.BIND_AUTO_CREATE)
- }
- Intent(this, NtripConnectService::class.java).also {
- startService(it)
- }
+// Intent(this, NtripConnectService::class.java).also {
+// startService(it)
+// }
soundResourceId = soundPool.load(this, R.raw.ring3, 1)
//右上角菜单
@@ -211,7 +138,7 @@
showMarkersOnMap()
}
- override fun onFailed(t: Throwable) {
+ override fun onDownloadFailed(t: Throwable) {
t.printStackTrace()
}
@@ -446,7 +373,7 @@
override fun onConfirmClick() {
isFreeTask = false
soundPool.autoPause()
- RuntimeCache.currentSegment = null
+ closeSerialPort()
binding.stopFreeTaskButton.visibility = View.GONE
if (freeTaskId.isNullOrBlank()) {
@@ -499,11 +426,7 @@
} else {
"此工单下无标识器,将执行自由巡检任务".show(context)
freeTaskId = task.taskId
-
- binding.stopFreeTaskButton.visibility = View.VISIBLE
- isFreeTask = true
- RuntimeCache.currentSegment = CurrentSegment.FreeInspection
- serialPortService?.writeCommand('2', '6')
+ detectMarker()
}
}
@@ -524,21 +447,22 @@
freeTaskTitle = value
val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String
taskViewModel.createFreeTask(context, userId, value)
-
- binding.stopFreeTaskButton.visibility = View.VISIBLE
- isFreeTask = true
- RuntimeCache.currentSegment = CurrentSegment.FreeInspection
- serialPortService?.writeCommand('2', '6')
+ detectMarker()
}
override fun onCancelClick() {}
}).build().show()
}
- override fun handleMessage(msg: Message): Boolean {
- if (msg.what == LocaleConstant.FREE_INSPECTION) {
- val buffer = msg.obj as ByteArray
- //只响一次,因为探测频率高,所以依旧是连续的报警声
+ private fun detectMarker() {
+ binding.stopFreeTaskButton.visibility = View.VISIBLE
+ isFreeTask = true
+ openSerialPort()
+ searchMarker(CurrentSegment.FreeInspection)
+ }
+
+ override fun onDataReceived(buffer: ByteArray, segment: CurrentSegment) {
+ if (segment == CurrentSegment.FreeInspection) {
soundPool.play(soundResourceId, 1f, 1f, 0, 0, 1f)
when ((buffer.first().toInt() and 0xFF).toString(16).uppercase()) {
"4E" -> {
@@ -552,27 +476,30 @@
val markerId = buffer.toMarkerId()
//添加地图Marker
if (!ids.contains(markerId)) {
- //根据markerId查询标识器经纬度
- val labels = DataBaseManager.get.queryMarkerById(markerId)
- if (labels.isNotEmpty()) {
- val bean = labels.first()
- aMap.addMarker(
- MarkerOptions()
- .position(LatLng(bean.lat.toDouble(), bean.lng.toDouble()))
- .icon(BitmapDescriptorFactory.fromResource(R.mipmap.label_blue1))
+ val markers = DataBaseManager.get.queryMarkerById(markerId)
+ if (markers.isNotEmpty()) {
+ val marker = markers.first()
+ val latLng = LatLng(
+ marker.lat.toDouble(), marker.lng.toDouble()
)
+ val resource = BitmapDescriptorFactory.fromResource(
+ R.mipmap.label_blue1
+ )
+ val options = MarkerOptions().position(latLng).icon(resource)
+ aMap.addMarker(options)
}
}
ids.add(markerId)
//显示标识器详细信息
if (!detailDialog.isShowing) {
- val markerBean = DataBaseManager.get.queryMarkerById(markerId).firstOrNull()
- if (markerBean == null) {
- "无法查询到此ID【${markerId}】的信息".show(context)
- } else {
- detailDialog.setMarker(markerBean)
- detailDialog.show()
+ DataBaseManager.get.queryMarkerById(markerId).firstOrNull().apply {
+ if (this == null) {
+ "无法查询到此ID【${markerId}】的信息".show(context)
+ } else {
+ detailDialog.setMarker(this)
+ detailDialog.show()
+ }
}
}
}
@@ -582,7 +509,6 @@
}
}
}
- return true
}
override fun observeRequestState() {
@@ -865,9 +791,6 @@
override fun onResume() {
super.onResume()
binding.mapView.onResume()
- if (serialPortService != null) {
- openSerialPort()
- }
}
override fun onPause() {
@@ -885,8 +808,6 @@
binding.mapView.onDestroy()
soundPool.autoPause()
locationKit.stopLocation()
- unbindService(serviceConnection)
- closeSerialPort()
BaseApplication.get().closeSerialPort()
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/SatelliteStatusActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/SatelliteStatusActivity.kt
index 9f2d5cd..0f1611d 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/SatelliteStatusActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/SatelliteStatusActivity.kt
@@ -74,7 +74,7 @@
locationManager.registerGnssStatusCallback(gnssStatusListener, null)
satelliteAdapter = SatelliteRecyclerAdapter(this, satelliteCollection)
binding.recyclerView.adapter = satelliteAdapter
- binding.recyclerView.addItemDecoration(RecyclerViewItemDivider(1, Color.WHITE))
+ binding.recyclerView.addItemDecoration(RecyclerViewItemDivider(0f, 0f, Color.WHITE))
//高德定位
locationKit.getCurrentLocation(false, object : OnGetLocationListener {
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt
index c7c8bb9..5417e1f 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt
@@ -1,9 +1,5 @@
package com.casic.common.detector.gd.view
-import android.content.ComponentName
-import android.content.Context
-import android.content.Intent
-import android.content.ServiceConnection
import android.graphics.Color
import android.hardware.Sensor
import android.hardware.SensorEvent
@@ -13,9 +9,6 @@
import android.media.SoundPool
import android.os.Bundle
import android.os.CountDownTimer
-import android.os.Handler
-import android.os.IBinder
-import android.os.Message
import android.util.Log
import android.view.View
import android.view.WindowManager
@@ -25,28 +18,25 @@
import com.amap.api.maps.AMapUtils
import com.amap.api.maps.model.LatLng
import com.casic.common.detector.gd.R
+import com.casic.common.detector.gd.base.SerialPortActivity
import com.casic.common.detector.gd.callback.OnGetLocationListener
import com.casic.common.detector.gd.databinding.ActivitySearchMarkerBinding
import com.casic.common.detector.gd.extensions.toBuryDepth
import com.casic.common.detector.gd.extensions.toMarkerId
import com.casic.common.detector.gd.extensions.toSignalStrength
import com.casic.common.detector.gd.model.MarkerDistanceData
-import com.casic.common.detector.gd.service.SerialPortService
import com.casic.common.detector.gd.utils.CurrentSegment
import com.casic.common.detector.gd.utils.DataBaseManager
import com.casic.common.detector.gd.utils.LocaleConstant
import com.casic.common.detector.gd.utils.LocationKit
-import com.casic.common.detector.gd.utils.RuntimeCache
import com.casic.common.detector.gd.vm.TaskViewModel
import com.casic.common.detector.gd.widgets.RadarScanView
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.getSystemService
import com.pengxh.kt.lite.extensions.navigatePageTo
import com.pengxh.kt.lite.extensions.show
import com.pengxh.kt.lite.utils.LiteKitConstant
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.utils.SaveKeyValues
-import com.pengxh.kt.lite.utils.WeakReferenceHandler
import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -55,8 +45,8 @@
import java.util.TimerTask
import kotlin.math.atan2
-class SearchMarkerActivity : KotlinBaseActivity(),
- SensorEventListener, Handler.Callback {
+class SearchMarkerActivity : SerialPortActivity(),
+ SensorEventListener {
private val kTag = "SearchMarkerActivity"
private val context = this
@@ -76,38 +66,10 @@
private var signalEnergy = 0 //标识器信号强度
private var gravity: FloatArray? = null
private var geomagnetic: FloatArray? = null
- private var serialPortService: SerialPortService? = null
- private lateinit var searchSignalEnergyTimer: Timer
-
- private val serviceConnection = object : ServiceConnection {
- override fun onServiceConnected(name: ComponentName?, iBinder: IBinder?) {
- if (name != null && iBinder != null && iBinder is SerialPortService.ServiceBinder) {
- try {
- serialPortService = iBinder.getSerialPortService()
- Log.d(kTag, "onServiceConnected: 服务已绑定,开始搜索标识器")
- searchMarker()
- } catch (e: Exception) {
- Log.e(kTag, "onServiceConnected: 绑定服务时发生异常", e)
- }
- } else {
- Log.w(kTag, "onServiceConnected: name 或 iBinder 为 null")
- }
- }
-
- override fun onServiceDisconnected(name: ComponentName?) {
-
- }
- }
-
- companion object {
- var weakReferenceHandler: WeakReferenceHandler? = null
- }
override fun initOnCreate(savedInstanceState: Bundle?) {
- weakReferenceHandler = WeakReferenceHandler(this)
-
- val flag = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY) as String
- isExecuteTask = flag != "0"
+ val taskState = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY) as String
+ isExecuteTask = taskState != "0"
slowSoundResourceId = soundPool.load(this, R.raw.ring4, 1)
fastSoundResourceId = soundPool.load(this, R.raw.ring2, 1)
@@ -131,14 +93,11 @@
binding.taskStateView.isSelected = true
}
- //绑定串口通信服务
- Intent(this, SerialPortService::class.java).also {
- bindService(it, serviceConnection, Context.BIND_AUTO_CREATE)
- }
+ openSerialPort()
+ searchMarker(CurrentSegment.SearchMarker)
//在标识器信号强度很强的时候,从数据库中计算出距离最近的点,以防出现探测不到ID的情况
- searchSignalEnergyTimer = Timer()
- searchSignalEnergyTimer.schedule(object : TimerTask() {
+ Timer().schedule(object : TimerTask() {
override fun run() {
if (signalEnergy <= 700) {//18°
runOnUiThread {
@@ -183,21 +142,8 @@
}, 0, 2000)
}
- private val countDownTimer = object : CountDownTimer(10 * 1000, 1000) {
- override fun onTick(millisUntilFinished: Long) {
-
- }
-
- override fun onFinish() {
- LoadingDialog.dismiss()
- "标识器深度探测超时,请移动位置重试".show(context)
- searchMarker()
- }
- }
-
override fun initEvent() {
binding.depthButton.setOnClickListener {
- soundPool.autoPause()
val result = DataBaseManager.get.queryMarkerById(markerId)
if (result.isNotEmpty()) {
val tag = when (result.first().markerType) {
@@ -208,18 +154,25 @@
}
if (tag == '1') {
"此标识器无法读取埋深!".show(this)
- searchMarker()
} else {
+ soundPool.autoPause()
LoadingDialog.show(this, "正在探测标识器埋深,请稍后...")
- countDownTimer.start()
// 发送读取标识器埋设深度指令
- RuntimeCache.currentSegment = CurrentSegment.DetectMarkerDepth
- serialPortService?.writeCommand(tag)
+ detectDepth(tag)
+ object : CountDownTimer(3 * 1000, 1000) {
+ override fun onTick(millisUntilFinished: Long) {
+
+ }
+
+ override fun onFinish() {
+ LoadingDialog.dismiss()
+ updateSegment(CurrentSegment.SearchMarker)
+ }
+ }.start()
}
} else {
LoadingDialog.dismiss()
"标识器未安装,安装成功后才可读取埋深!".show(this)
- searchMarker()
}
}
@@ -236,13 +189,11 @@
}
}
- override fun handleMessage(msg: Message): Boolean {
- val buffer = msg.obj as ByteArray
- if (msg.what == LocaleConstant.DETECT_MARKER_DEPTH) {
- val tag = (buffer.first().toInt() and 0xFF).toString(16).uppercase()
- if (tag == "53") {
+ override fun onDataReceived(buffer: ByteArray, segment: CurrentSegment) {
+ if (segment == CurrentSegment.DetectDepth) {
+ val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase()
+ if (flag == "53" && buffer.size == 5) {
LoadingDialog.dismiss()
- countDownTimer.cancel()
try {
AlertMessageDialog.Builder().setContext(context)
.setTitle("温馨提示")
@@ -251,54 +202,32 @@
.setOnDialogButtonClickListener(object :
AlertMessageDialog.OnDialogButtonClickListener {
override fun onConfirmClick() {
- searchMarker()
+ updateSegment(CurrentSegment.SearchMarker)
}
}).build().show()
} catch (e: WindowManager.BadTokenException) {
e.printStackTrace()
- } catch (e: NumberFormatException) {
- e.printStackTrace()
}
}
- } else if (msg.what == LocaleConstant.SEARCH_MARKER) {
- try {
- // 读取到信号强度
- when ((buffer.first().toInt() and 0xFF).toString(16).uppercase()) {
- "4E" -> {
- val signalEnergy = buffer.toSignalStrength()
+ } else if (segment == CurrentSegment.SearchMarker) {
+ val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase()
+ if (flag == "30" && buffer.size == 10) {
+ handleMarker(buffer.toMarkerId())
+ } else if (flag == "4E" && buffer.size == 5) {
+ val signalEnergy = buffer.toSignalStrength()
- //声音
- updateSound(signalEnergy)
+ //声音
+ updateSound(signalEnergy)
- //信号强度显示
- updateProgressBar(signalEnergy)
+ //信号强度显示
+ updateProgressBar(signalEnergy)
- //搜索信号文字显示
- updateTextResult(signalEnergy)
- }
-
- "30" -> {
- handleMarker(buffer.toMarkerId())
- }
-
- else -> {
- Log.d(kTag, "乱码数据: ${buffer.contentToString()}")
- }
- }
- } catch (e: Exception) {
- e.printStackTrace()
- Log.e(kTag, "Error processing buffer data", e)
+ //搜索信号文字显示
+ updateTextResult(signalEnergy)
+ } else {
+ Log.d(kTag, "乱码数据: ${buffer.contentToString()}")
}
}
- return true
- }
-
- /**
- * 搜索标识器
- * */
- private fun searchMarker() {
- RuntimeCache.currentSegment = CurrentSegment.SearchMarker
- serialPortService?.writeCommand('2', '6')
}
private fun updateSound(signalEnergy: Int) {
@@ -492,9 +421,8 @@
override fun onDestroy() {
super.onDestroy()
+ closeSerialPort()
soundPool.autoPause()
- RuntimeCache.currentSegment = null
locationKit.stopLocation()
- unbindService(serviceConnection)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/common/detector/gd/view/VersionControlActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/VersionControlActivity.kt
index ddc5a32..8641c79 100644
--- a/app/src/main/java/com/casic/common/detector/gd/view/VersionControlActivity.kt
+++ b/app/src/main/java/com/casic/common/detector/gd/view/VersionControlActivity.kt
@@ -13,17 +13,17 @@
import com.casic.common.detector.gd.databinding.ActivityVersionControlBinding
import com.casic.common.detector.gd.extensions.appendDownloadUrl
import com.casic.common.detector.gd.extensions.initImmersionBar
-import com.casic.common.detector.gd.utils.FileDownloadManager
import com.casic.common.detector.gd.utils.FileType
import com.casic.common.detector.gd.vm.VersionViewModel
-import com.casic.common.detector.gd.widgets.ProgressDialog
import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.createDownloadFileDir
import com.pengxh.kt.lite.extensions.show
+import com.pengxh.kt.lite.utils.FileDownloadManager
import com.pengxh.kt.lite.utils.LoadState
import com.pengxh.kt.lite.utils.LoadingDialog
import com.pengxh.kt.lite.widget.TitleBarView
import com.pengxh.kt.lite.widget.dialog.AlertControlDialog
+import com.pengxh.kt.lite.widget.dialog.ProgressDialog
import java.io.File
class VersionControlActivity : KotlinBaseActivity() {
@@ -118,7 +118,7 @@
installApk(file)
}
- override fun onFailed(t: Throwable) {
+ override fun onDownloadFailed(t: Throwable) {
t.printStackTrace()
progressDialog.dismiss()
}
diff --git a/app/src/main/java/com/casic/common/detector/gd/widgets/ProgressDialog.kt b/app/src/main/java/com/casic/common/detector/gd/widgets/ProgressDialog.kt
deleted file mode 100644
index af480b0..0000000
--- a/app/src/main/java/com/casic/common/detector/gd/widgets/ProgressDialog.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.casic.common.detector.gd.widgets
-
-import android.app.Dialog
-import android.content.Context
-import android.os.Bundle
-import com.casic.common.detector.gd.databinding.DialogProgressBinding
-import com.pengxh.kt.lite.R
-import com.pengxh.kt.lite.extensions.binding
-import com.pengxh.kt.lite.extensions.initDialogLayoutParams
-
-class ProgressDialog(context: Context) : Dialog(context, R.style.UserDefinedDialogStyle) {
-
- private val binding: DialogProgressBinding by binding()
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- this.initDialogLayoutParams(0.5f)
- setCanceledOnTouchOutside(false)
- setCancelable(false)
- binding.progressBar.progress = 0
- binding.progressText.text = "0 %"
- }
-
- fun setMaxProgress(maxProgress: Long) {
- binding.progressBar.max = maxProgress.toInt()
- }
-
- private fun getMaxProgress() = binding.progressBar.max
-
- fun updateProgress(progress: Long) {
- binding.progressBar.progress = progress.toInt()
-
- val percent = (progress.toFloat() / getMaxProgress()) * 100
- binding.progressText.text = String.format("%.2f %%", percent)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_version_control.xml b/app/src/main/res/layout/activity_version_control.xml
index 887248f..15f3a91 100644
--- a/app/src/main/res/layout/activity_version_control.xml
+++ b/app/src/main/res/layout/activity_version_control.xml
@@ -81,7 +81,6 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file