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 e5fe1f5..7b695ff 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,22 +1,35 @@ package com.casic.common.detector.gd.base +import android.app.Activity import android.app.Application +import android.os.Bundle 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 +import com.casic.common.detector.gd.utils.GpioManager import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.SaveKeyValues import com.tencent.bugly.crashreport.CrashReport import java.io.File import java.io.IOException import java.security.InvalidParameterException +import java.util.concurrent.atomic.AtomicInteger import kotlin.properties.Delegates -class BaseApplication : Application() { +class BaseApplication : Application(), Application.ActivityLifecycleCallbacks { private val kTag = "BaseApplication" private var serialPorts = ArrayList() + private var activityReferences = 0 + private var isActivityChangingConfigurations = false + private val gpioManager by lazy { GpioManager() } + + /** + * 读取数据 1 + * 暂停读取 0 + * */ + private val gpioState = AtomicInteger(0) fun getSerialPorts(): ArrayList = serialPorts @@ -49,7 +62,6 @@ try { serialPorts.apply { add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) - add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) //千寻报文数据下发串口号 add(SerialPort(File("/dev/ttyS1"), 9600, 0)) } @@ -61,9 +73,67 @@ } catch (e: InvalidParameterException) { "请检查串口!".show(this) } + + registerActivityLifecycleCallbacks(this) } fun getDaoSession(): DaoSession { return daoSession } + + override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { + + } + + override fun onActivityStarted(activity: Activity) { + if (++activityReferences == 1 && !isActivityChangingConfigurations) { + onAppForeground() + } + } + + override fun onActivityResumed(activity: Activity) { + + } + + override fun onActivityPaused(activity: Activity) { + + } + + override fun onActivityStopped(activity: Activity) { + isActivityChangingConfigurations = activity.isChangingConfigurations + if (--activityReferences == 0 && !isActivityChangingConfigurations) { + onAppBackground() + } + } + + override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) { + + } + + override fun onActivityDestroyed(activity: Activity) { + + } + + private fun onAppForeground() { + Log.d(kTag, "onAppForeground: 处于前台") + if (gpioState.get() != 1) { + gpioManager.setGpioHigh("18") + gpioState.set(1) + Log.d(kTag, "调高串口电位") + } else { + Log.d(kTag, "已经是高电位,直接读数据") + } + } + + private fun onAppBackground() { + Log.d(kTag, "onAppBackground: 退到后台") + if (gpioState.get() == 0) { + Log.d(kTag, "已经是低电位,不响应") + return + } + // 降低串口电位 + gpioManager.setGpioLow("18") + gpioState.set(0) + Log.d(kTag, "降低串口电位") + } } \ No newline at end of file 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 e5fe1f5..7b695ff 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,22 +1,35 @@ package com.casic.common.detector.gd.base +import android.app.Activity import android.app.Application +import android.os.Bundle 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 +import com.casic.common.detector.gd.utils.GpioManager import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.SaveKeyValues import com.tencent.bugly.crashreport.CrashReport import java.io.File import java.io.IOException import java.security.InvalidParameterException +import java.util.concurrent.atomic.AtomicInteger import kotlin.properties.Delegates -class BaseApplication : Application() { +class BaseApplication : Application(), Application.ActivityLifecycleCallbacks { private val kTag = "BaseApplication" private var serialPorts = ArrayList() + private var activityReferences = 0 + private var isActivityChangingConfigurations = false + private val gpioManager by lazy { GpioManager() } + + /** + * 读取数据 1 + * 暂停读取 0 + * */ + private val gpioState = AtomicInteger(0) fun getSerialPorts(): ArrayList = serialPorts @@ -49,7 +62,6 @@ try { serialPorts.apply { add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) - add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) //千寻报文数据下发串口号 add(SerialPort(File("/dev/ttyS1"), 9600, 0)) } @@ -61,9 +73,67 @@ } catch (e: InvalidParameterException) { "请检查串口!".show(this) } + + registerActivityLifecycleCallbacks(this) } fun getDaoSession(): DaoSession { return daoSession } + + override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { + + } + + override fun onActivityStarted(activity: Activity) { + if (++activityReferences == 1 && !isActivityChangingConfigurations) { + onAppForeground() + } + } + + override fun onActivityResumed(activity: Activity) { + + } + + override fun onActivityPaused(activity: Activity) { + + } + + override fun onActivityStopped(activity: Activity) { + isActivityChangingConfigurations = activity.isChangingConfigurations + if (--activityReferences == 0 && !isActivityChangingConfigurations) { + onAppBackground() + } + } + + override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) { + + } + + override fun onActivityDestroyed(activity: Activity) { + + } + + private fun onAppForeground() { + Log.d(kTag, "onAppForeground: 处于前台") + if (gpioState.get() != 1) { + gpioManager.setGpioHigh("18") + gpioState.set(1) + Log.d(kTag, "调高串口电位") + } else { + Log.d(kTag, "已经是高电位,直接读数据") + } + } + + private fun onAppBackground() { + Log.d(kTag, "onAppBackground: 退到后台") + if (gpioState.get() == 0) { + Log.d(kTag, "已经是低电位,不响应") + return + } + // 降低串口电位 + gpioManager.setGpioLow("18") + gpioState.set(0) + Log.d(kTag, "降低串口电位") + } } \ No newline at end of file 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 deleted file mode 100644 index 08b3e19..0000000 --- a/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt +++ /dev/null @@ -1,204 +0,0 @@ -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/base/BaseApplication.kt b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt index e5fe1f5..7b695ff 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,22 +1,35 @@ package com.casic.common.detector.gd.base +import android.app.Activity import android.app.Application +import android.os.Bundle 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 +import com.casic.common.detector.gd.utils.GpioManager import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.SaveKeyValues import com.tencent.bugly.crashreport.CrashReport import java.io.File import java.io.IOException import java.security.InvalidParameterException +import java.util.concurrent.atomic.AtomicInteger import kotlin.properties.Delegates -class BaseApplication : Application() { +class BaseApplication : Application(), Application.ActivityLifecycleCallbacks { private val kTag = "BaseApplication" private var serialPorts = ArrayList() + private var activityReferences = 0 + private var isActivityChangingConfigurations = false + private val gpioManager by lazy { GpioManager() } + + /** + * 读取数据 1 + * 暂停读取 0 + * */ + private val gpioState = AtomicInteger(0) fun getSerialPorts(): ArrayList = serialPorts @@ -49,7 +62,6 @@ try { serialPorts.apply { add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) - add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) //千寻报文数据下发串口号 add(SerialPort(File("/dev/ttyS1"), 9600, 0)) } @@ -61,9 +73,67 @@ } catch (e: InvalidParameterException) { "请检查串口!".show(this) } + + registerActivityLifecycleCallbacks(this) } fun getDaoSession(): DaoSession { return daoSession } + + override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { + + } + + override fun onActivityStarted(activity: Activity) { + if (++activityReferences == 1 && !isActivityChangingConfigurations) { + onAppForeground() + } + } + + override fun onActivityResumed(activity: Activity) { + + } + + override fun onActivityPaused(activity: Activity) { + + } + + override fun onActivityStopped(activity: Activity) { + isActivityChangingConfigurations = activity.isChangingConfigurations + if (--activityReferences == 0 && !isActivityChangingConfigurations) { + onAppBackground() + } + } + + override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) { + + } + + override fun onActivityDestroyed(activity: Activity) { + + } + + private fun onAppForeground() { + Log.d(kTag, "onAppForeground: 处于前台") + if (gpioState.get() != 1) { + gpioManager.setGpioHigh("18") + gpioState.set(1) + Log.d(kTag, "调高串口电位") + } else { + Log.d(kTag, "已经是高电位,直接读数据") + } + } + + private fun onAppBackground() { + Log.d(kTag, "onAppBackground: 退到后台") + if (gpioState.get() == 0) { + Log.d(kTag, "已经是低电位,不响应") + return + } + // 降低串口电位 + gpioManager.setGpioLow("18") + gpioState.set(0) + Log.d(kTag, "降低串口电位") + } } \ No newline at end of file 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 deleted file mode 100644 index 08b3e19..0000000 --- a/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt +++ /dev/null @@ -1,204 +0,0 @@ -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/base/SerialPortBaseActivity.kt b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortBaseActivity.kt new file mode 100644 index 0000000..b6eeab5 --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortBaseActivity.kt @@ -0,0 +1,139 @@ +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.extensions.toBuryDepth +import com.casic.common.detector.gd.extensions.toMarkerId +import com.casic.common.detector.gd.extensions.toSignalStrength +import com.casic.common.detector.gd.utils.CurrentSegment +import com.casic.common.detector.gd.utils.RuntimeCache +import com.casic.common.detector.gd.utils.SerialPortCommand +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import java.io.IOException +import java.util.Timer + +abstract class SerialPortBaseActivity : AppCompatActivity(), Handler.Callback { + + private val kTag = "SerialPortBaseActivity" + private val taskTimer by lazy { Timer() } + private val weakReferenceHandler by lazy { WeakReferenceHandler(this) } + + //输出流 + private val outStream by lazy { BaseApplication.get().getSerialPorts()[0].outputStream } + + //输入流 + private val inStream by lazy { BaseApplication.get().getSerialPorts()[0].inputStream } + + 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 = inStream.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 onMarkerIdDetected(markerId: String) + + abstract fun onMarkerDepthDetected(depth: Int) + + abstract fun onMarkerSignalDetected(signalEnergy: Int) + + override fun handleMessage(msg: Message): Boolean { + if (msg.what == 2025012001) { + val buffer = msg.obj as ByteArray + Log.d(kTag, "${RuntimeCache.currentSegment} ${buffer.contentToString()}") + val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase() + if (RuntimeCache.currentSegment == CurrentSegment.InstallMarker && flag == "30" && buffer.size == 10) { + onMarkerIdDetected(buffer.toMarkerId()) + } else if (RuntimeCache.currentSegment == CurrentSegment.FreeInspection) { + if (flag == "30" && buffer.size == 10) { + onMarkerIdDetected(buffer.toMarkerId()) + } else if (flag == "4E" && buffer.size == 5) { + onMarkerSignalDetected(buffer.toSignalStrength()) + } + } else if (RuntimeCache.currentSegment == CurrentSegment.SearchMarker) { + if (flag == "30" && buffer.size == 10) { + onMarkerIdDetected(buffer.toMarkerId()) + } else if (flag == "4E" && buffer.size == 5) { + onMarkerSignalDetected(buffer.toSignalStrength()) + } + } else if (RuntimeCache.currentSegment == CurrentSegment.DetectDepth) { + if (flag == "53" && buffer.size == 5) { + onMarkerDepthDetected(buffer.toBuryDepth()) + } + } + } + return true + } + + fun sendSerialPortCommand(command: Int) { + outStream.write(command) + outStream.flush() + Log.d(kTag, "sendSerialPortCommand: $command") + } + + /** + * 停止串口数据传输 + * */ + fun stopSerialPortCommand() { + outStream.write(SerialPortCommand.STOP_SERIAL_PORT_DATA) + outStream.flush() + } + + override fun onDestroy() { + super.onDestroy() + stopSerialPortCommand() + } +} \ No newline at end of file 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 e5fe1f5..7b695ff 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,22 +1,35 @@ package com.casic.common.detector.gd.base +import android.app.Activity import android.app.Application +import android.os.Bundle 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 +import com.casic.common.detector.gd.utils.GpioManager import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.SaveKeyValues import com.tencent.bugly.crashreport.CrashReport import java.io.File import java.io.IOException import java.security.InvalidParameterException +import java.util.concurrent.atomic.AtomicInteger import kotlin.properties.Delegates -class BaseApplication : Application() { +class BaseApplication : Application(), Application.ActivityLifecycleCallbacks { private val kTag = "BaseApplication" private var serialPorts = ArrayList() + private var activityReferences = 0 + private var isActivityChangingConfigurations = false + private val gpioManager by lazy { GpioManager() } + + /** + * 读取数据 1 + * 暂停读取 0 + * */ + private val gpioState = AtomicInteger(0) fun getSerialPorts(): ArrayList = serialPorts @@ -49,7 +62,6 @@ try { serialPorts.apply { add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) - add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) //千寻报文数据下发串口号 add(SerialPort(File("/dev/ttyS1"), 9600, 0)) } @@ -61,9 +73,67 @@ } catch (e: InvalidParameterException) { "请检查串口!".show(this) } + + registerActivityLifecycleCallbacks(this) } fun getDaoSession(): DaoSession { return daoSession } + + override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { + + } + + override fun onActivityStarted(activity: Activity) { + if (++activityReferences == 1 && !isActivityChangingConfigurations) { + onAppForeground() + } + } + + override fun onActivityResumed(activity: Activity) { + + } + + override fun onActivityPaused(activity: Activity) { + + } + + override fun onActivityStopped(activity: Activity) { + isActivityChangingConfigurations = activity.isChangingConfigurations + if (--activityReferences == 0 && !isActivityChangingConfigurations) { + onAppBackground() + } + } + + override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) { + + } + + override fun onActivityDestroyed(activity: Activity) { + + } + + private fun onAppForeground() { + Log.d(kTag, "onAppForeground: 处于前台") + if (gpioState.get() != 1) { + gpioManager.setGpioHigh("18") + gpioState.set(1) + Log.d(kTag, "调高串口电位") + } else { + Log.d(kTag, "已经是高电位,直接读数据") + } + } + + private fun onAppBackground() { + Log.d(kTag, "onAppBackground: 退到后台") + if (gpioState.get() == 0) { + Log.d(kTag, "已经是低电位,不响应") + return + } + // 降低串口电位 + gpioManager.setGpioLow("18") + gpioState.set(0) + Log.d(kTag, "降低串口电位") + } } \ No newline at end of file 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 deleted file mode 100644 index 08b3e19..0000000 --- a/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt +++ /dev/null @@ -1,204 +0,0 @@ -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/base/SerialPortBaseActivity.kt b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortBaseActivity.kt new file mode 100644 index 0000000..b6eeab5 --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortBaseActivity.kt @@ -0,0 +1,139 @@ +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.extensions.toBuryDepth +import com.casic.common.detector.gd.extensions.toMarkerId +import com.casic.common.detector.gd.extensions.toSignalStrength +import com.casic.common.detector.gd.utils.CurrentSegment +import com.casic.common.detector.gd.utils.RuntimeCache +import com.casic.common.detector.gd.utils.SerialPortCommand +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import java.io.IOException +import java.util.Timer + +abstract class SerialPortBaseActivity : AppCompatActivity(), Handler.Callback { + + private val kTag = "SerialPortBaseActivity" + private val taskTimer by lazy { Timer() } + private val weakReferenceHandler by lazy { WeakReferenceHandler(this) } + + //输出流 + private val outStream by lazy { BaseApplication.get().getSerialPorts()[0].outputStream } + + //输入流 + private val inStream by lazy { BaseApplication.get().getSerialPorts()[0].inputStream } + + 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 = inStream.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 onMarkerIdDetected(markerId: String) + + abstract fun onMarkerDepthDetected(depth: Int) + + abstract fun onMarkerSignalDetected(signalEnergy: Int) + + override fun handleMessage(msg: Message): Boolean { + if (msg.what == 2025012001) { + val buffer = msg.obj as ByteArray + Log.d(kTag, "${RuntimeCache.currentSegment} ${buffer.contentToString()}") + val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase() + if (RuntimeCache.currentSegment == CurrentSegment.InstallMarker && flag == "30" && buffer.size == 10) { + onMarkerIdDetected(buffer.toMarkerId()) + } else if (RuntimeCache.currentSegment == CurrentSegment.FreeInspection) { + if (flag == "30" && buffer.size == 10) { + onMarkerIdDetected(buffer.toMarkerId()) + } else if (flag == "4E" && buffer.size == 5) { + onMarkerSignalDetected(buffer.toSignalStrength()) + } + } else if (RuntimeCache.currentSegment == CurrentSegment.SearchMarker) { + if (flag == "30" && buffer.size == 10) { + onMarkerIdDetected(buffer.toMarkerId()) + } else if (flag == "4E" && buffer.size == 5) { + onMarkerSignalDetected(buffer.toSignalStrength()) + } + } else if (RuntimeCache.currentSegment == CurrentSegment.DetectDepth) { + if (flag == "53" && buffer.size == 5) { + onMarkerDepthDetected(buffer.toBuryDepth()) + } + } + } + return true + } + + fun sendSerialPortCommand(command: Int) { + outStream.write(command) + outStream.flush() + Log.d(kTag, "sendSerialPortCommand: $command") + } + + /** + * 停止串口数据传输 + * */ + fun stopSerialPortCommand() { + outStream.write(SerialPortCommand.STOP_SERIAL_PORT_DATA) + outStream.flush() + } + + override fun onDestroy() { + super.onDestroy() + stopSerialPortCommand() + } +} \ 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 5c3ee01..6994136 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 @@ -22,6 +22,7 @@ * * [48, 48, 48, 56, 56, 57, 49, 48, 55, 51] * + * 只从串口:/dev/ttysWK1 出来 * */ fun ByteArray.toMarkerId(): String { val id = this.map { it.toInt().toChar() }.joinToString("") 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 e5fe1f5..7b695ff 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,22 +1,35 @@ package com.casic.common.detector.gd.base +import android.app.Activity import android.app.Application +import android.os.Bundle 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 +import com.casic.common.detector.gd.utils.GpioManager import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.SaveKeyValues import com.tencent.bugly.crashreport.CrashReport import java.io.File import java.io.IOException import java.security.InvalidParameterException +import java.util.concurrent.atomic.AtomicInteger import kotlin.properties.Delegates -class BaseApplication : Application() { +class BaseApplication : Application(), Application.ActivityLifecycleCallbacks { private val kTag = "BaseApplication" private var serialPorts = ArrayList() + private var activityReferences = 0 + private var isActivityChangingConfigurations = false + private val gpioManager by lazy { GpioManager() } + + /** + * 读取数据 1 + * 暂停读取 0 + * */ + private val gpioState = AtomicInteger(0) fun getSerialPorts(): ArrayList = serialPorts @@ -49,7 +62,6 @@ try { serialPorts.apply { add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) - add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) //千寻报文数据下发串口号 add(SerialPort(File("/dev/ttyS1"), 9600, 0)) } @@ -61,9 +73,67 @@ } catch (e: InvalidParameterException) { "请检查串口!".show(this) } + + registerActivityLifecycleCallbacks(this) } fun getDaoSession(): DaoSession { return daoSession } + + override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { + + } + + override fun onActivityStarted(activity: Activity) { + if (++activityReferences == 1 && !isActivityChangingConfigurations) { + onAppForeground() + } + } + + override fun onActivityResumed(activity: Activity) { + + } + + override fun onActivityPaused(activity: Activity) { + + } + + override fun onActivityStopped(activity: Activity) { + isActivityChangingConfigurations = activity.isChangingConfigurations + if (--activityReferences == 0 && !isActivityChangingConfigurations) { + onAppBackground() + } + } + + override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) { + + } + + override fun onActivityDestroyed(activity: Activity) { + + } + + private fun onAppForeground() { + Log.d(kTag, "onAppForeground: 处于前台") + if (gpioState.get() != 1) { + gpioManager.setGpioHigh("18") + gpioState.set(1) + Log.d(kTag, "调高串口电位") + } else { + Log.d(kTag, "已经是高电位,直接读数据") + } + } + + private fun onAppBackground() { + Log.d(kTag, "onAppBackground: 退到后台") + if (gpioState.get() == 0) { + Log.d(kTag, "已经是低电位,不响应") + return + } + // 降低串口电位 + gpioManager.setGpioLow("18") + gpioState.set(0) + Log.d(kTag, "降低串口电位") + } } \ No newline at end of file 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 deleted file mode 100644 index 08b3e19..0000000 --- a/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt +++ /dev/null @@ -1,204 +0,0 @@ -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/base/SerialPortBaseActivity.kt b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortBaseActivity.kt new file mode 100644 index 0000000..b6eeab5 --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortBaseActivity.kt @@ -0,0 +1,139 @@ +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.extensions.toBuryDepth +import com.casic.common.detector.gd.extensions.toMarkerId +import com.casic.common.detector.gd.extensions.toSignalStrength +import com.casic.common.detector.gd.utils.CurrentSegment +import com.casic.common.detector.gd.utils.RuntimeCache +import com.casic.common.detector.gd.utils.SerialPortCommand +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import java.io.IOException +import java.util.Timer + +abstract class SerialPortBaseActivity : AppCompatActivity(), Handler.Callback { + + private val kTag = "SerialPortBaseActivity" + private val taskTimer by lazy { Timer() } + private val weakReferenceHandler by lazy { WeakReferenceHandler(this) } + + //输出流 + private val outStream by lazy { BaseApplication.get().getSerialPorts()[0].outputStream } + + //输入流 + private val inStream by lazy { BaseApplication.get().getSerialPorts()[0].inputStream } + + 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 = inStream.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 onMarkerIdDetected(markerId: String) + + abstract fun onMarkerDepthDetected(depth: Int) + + abstract fun onMarkerSignalDetected(signalEnergy: Int) + + override fun handleMessage(msg: Message): Boolean { + if (msg.what == 2025012001) { + val buffer = msg.obj as ByteArray + Log.d(kTag, "${RuntimeCache.currentSegment} ${buffer.contentToString()}") + val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase() + if (RuntimeCache.currentSegment == CurrentSegment.InstallMarker && flag == "30" && buffer.size == 10) { + onMarkerIdDetected(buffer.toMarkerId()) + } else if (RuntimeCache.currentSegment == CurrentSegment.FreeInspection) { + if (flag == "30" && buffer.size == 10) { + onMarkerIdDetected(buffer.toMarkerId()) + } else if (flag == "4E" && buffer.size == 5) { + onMarkerSignalDetected(buffer.toSignalStrength()) + } + } else if (RuntimeCache.currentSegment == CurrentSegment.SearchMarker) { + if (flag == "30" && buffer.size == 10) { + onMarkerIdDetected(buffer.toMarkerId()) + } else if (flag == "4E" && buffer.size == 5) { + onMarkerSignalDetected(buffer.toSignalStrength()) + } + } else if (RuntimeCache.currentSegment == CurrentSegment.DetectDepth) { + if (flag == "53" && buffer.size == 5) { + onMarkerDepthDetected(buffer.toBuryDepth()) + } + } + } + return true + } + + fun sendSerialPortCommand(command: Int) { + outStream.write(command) + outStream.flush() + Log.d(kTag, "sendSerialPortCommand: $command") + } + + /** + * 停止串口数据传输 + * */ + fun stopSerialPortCommand() { + outStream.write(SerialPortCommand.STOP_SERIAL_PORT_DATA) + outStream.flush() + } + + override fun onDestroy() { + super.onDestroy() + stopSerialPortCommand() + } +} \ 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 5c3ee01..6994136 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 @@ -22,6 +22,7 @@ * * [48, 48, 48, 56, 56, 57, 49, 48, 55, 51] * + * 只从串口:/dev/ttysWK1 出来 * */ fun ByteArray.toMarkerId(): String { val id = this.map { it.toInt().toChar() }.joinToString("") 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 new file mode 100644 index 0000000..104f971 --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt @@ -0,0 +1,5 @@ +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/base/BaseApplication.kt b/app/src/main/java/com/casic/common/detector/gd/base/BaseApplication.kt index e5fe1f5..7b695ff 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,22 +1,35 @@ package com.casic.common.detector.gd.base +import android.app.Activity import android.app.Application +import android.os.Bundle 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 +import com.casic.common.detector.gd.utils.GpioManager import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.SaveKeyValues import com.tencent.bugly.crashreport.CrashReport import java.io.File import java.io.IOException import java.security.InvalidParameterException +import java.util.concurrent.atomic.AtomicInteger import kotlin.properties.Delegates -class BaseApplication : Application() { +class BaseApplication : Application(), Application.ActivityLifecycleCallbacks { private val kTag = "BaseApplication" private var serialPorts = ArrayList() + private var activityReferences = 0 + private var isActivityChangingConfigurations = false + private val gpioManager by lazy { GpioManager() } + + /** + * 读取数据 1 + * 暂停读取 0 + * */ + private val gpioState = AtomicInteger(0) fun getSerialPorts(): ArrayList = serialPorts @@ -49,7 +62,6 @@ try { serialPorts.apply { add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) - add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) //千寻报文数据下发串口号 add(SerialPort(File("/dev/ttyS1"), 9600, 0)) } @@ -61,9 +73,67 @@ } catch (e: InvalidParameterException) { "请检查串口!".show(this) } + + registerActivityLifecycleCallbacks(this) } fun getDaoSession(): DaoSession { return daoSession } + + override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { + + } + + override fun onActivityStarted(activity: Activity) { + if (++activityReferences == 1 && !isActivityChangingConfigurations) { + onAppForeground() + } + } + + override fun onActivityResumed(activity: Activity) { + + } + + override fun onActivityPaused(activity: Activity) { + + } + + override fun onActivityStopped(activity: Activity) { + isActivityChangingConfigurations = activity.isChangingConfigurations + if (--activityReferences == 0 && !isActivityChangingConfigurations) { + onAppBackground() + } + } + + override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) { + + } + + override fun onActivityDestroyed(activity: Activity) { + + } + + private fun onAppForeground() { + Log.d(kTag, "onAppForeground: 处于前台") + if (gpioState.get() != 1) { + gpioManager.setGpioHigh("18") + gpioState.set(1) + Log.d(kTag, "调高串口电位") + } else { + Log.d(kTag, "已经是高电位,直接读数据") + } + } + + private fun onAppBackground() { + Log.d(kTag, "onAppBackground: 退到后台") + if (gpioState.get() == 0) { + Log.d(kTag, "已经是低电位,不响应") + return + } + // 降低串口电位 + gpioManager.setGpioLow("18") + gpioState.set(0) + Log.d(kTag, "降低串口电位") + } } \ No newline at end of file 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 deleted file mode 100644 index 08b3e19..0000000 --- a/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt +++ /dev/null @@ -1,204 +0,0 @@ -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/base/SerialPortBaseActivity.kt b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortBaseActivity.kt new file mode 100644 index 0000000..b6eeab5 --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortBaseActivity.kt @@ -0,0 +1,139 @@ +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.extensions.toBuryDepth +import com.casic.common.detector.gd.extensions.toMarkerId +import com.casic.common.detector.gd.extensions.toSignalStrength +import com.casic.common.detector.gd.utils.CurrentSegment +import com.casic.common.detector.gd.utils.RuntimeCache +import com.casic.common.detector.gd.utils.SerialPortCommand +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import java.io.IOException +import java.util.Timer + +abstract class SerialPortBaseActivity : AppCompatActivity(), Handler.Callback { + + private val kTag = "SerialPortBaseActivity" + private val taskTimer by lazy { Timer() } + private val weakReferenceHandler by lazy { WeakReferenceHandler(this) } + + //输出流 + private val outStream by lazy { BaseApplication.get().getSerialPorts()[0].outputStream } + + //输入流 + private val inStream by lazy { BaseApplication.get().getSerialPorts()[0].inputStream } + + 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 = inStream.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 onMarkerIdDetected(markerId: String) + + abstract fun onMarkerDepthDetected(depth: Int) + + abstract fun onMarkerSignalDetected(signalEnergy: Int) + + override fun handleMessage(msg: Message): Boolean { + if (msg.what == 2025012001) { + val buffer = msg.obj as ByteArray + Log.d(kTag, "${RuntimeCache.currentSegment} ${buffer.contentToString()}") + val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase() + if (RuntimeCache.currentSegment == CurrentSegment.InstallMarker && flag == "30" && buffer.size == 10) { + onMarkerIdDetected(buffer.toMarkerId()) + } else if (RuntimeCache.currentSegment == CurrentSegment.FreeInspection) { + if (flag == "30" && buffer.size == 10) { + onMarkerIdDetected(buffer.toMarkerId()) + } else if (flag == "4E" && buffer.size == 5) { + onMarkerSignalDetected(buffer.toSignalStrength()) + } + } else if (RuntimeCache.currentSegment == CurrentSegment.SearchMarker) { + if (flag == "30" && buffer.size == 10) { + onMarkerIdDetected(buffer.toMarkerId()) + } else if (flag == "4E" && buffer.size == 5) { + onMarkerSignalDetected(buffer.toSignalStrength()) + } + } else if (RuntimeCache.currentSegment == CurrentSegment.DetectDepth) { + if (flag == "53" && buffer.size == 5) { + onMarkerDepthDetected(buffer.toBuryDepth()) + } + } + } + return true + } + + fun sendSerialPortCommand(command: Int) { + outStream.write(command) + outStream.flush() + Log.d(kTag, "sendSerialPortCommand: $command") + } + + /** + * 停止串口数据传输 + * */ + fun stopSerialPortCommand() { + outStream.write(SerialPortCommand.STOP_SERIAL_PORT_DATA) + outStream.flush() + } + + override fun onDestroy() { + super.onDestroy() + stopSerialPortCommand() + } +} \ 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 5c3ee01..6994136 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 @@ -22,6 +22,7 @@ * * [48, 48, 48, 56, 56, 57, 49, 48, 55, 51] * + * 只从串口:/dev/ttysWK1 出来 * */ fun ByteArray.toMarkerId(): String { val id = this.map { it.toInt().toChar() }.joinToString("") 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 new file mode 100644 index 0000000..104f971 --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt @@ -0,0 +1,5 @@ +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/utils/SerialPortCommand.kt b/app/src/main/java/com/casic/common/detector/gd/utils/SerialPortCommand.kt new file mode 100644 index 0000000..8db2785 --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/utils/SerialPortCommand.kt @@ -0,0 +1,31 @@ +package com.casic.common.detector.gd.utils + +object SerialPortCommand { + /** + * 发送一次指令,会返回2次设备ID + * */ + const val SEARCH_MARKER_ONCE = '1'.code + + /** + * 发送一次指令,会不停的返回设备ID + * */ + const val SEARCH_MARKER_ALWAYS = '2'.code + + /** + * 串口停止发送数据 + * 3/4/5均可 + * */ + const val STOP_SERIAL_PORT_DATA = '3'.code + + /** + * 发送一次指令,会不停的返回信号强度(电磁感应) + * */ + const val SEARCH_SIGNAL = '6'.code + + /** + * 探测深度,均为一次性的,且测距会把[SEARCH_SIGNAL]和[SEARCH_MARKER_ALWAYS]中断 + * */ + const val DETECT_EM30_DEPTH = '7'.code + const val DETECT_EM50_DEPTH = '8'.code + const val DETECT_EM14_DEPTH = '9'.code +} \ No newline at end of file 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 e5fe1f5..7b695ff 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,22 +1,35 @@ package com.casic.common.detector.gd.base +import android.app.Activity import android.app.Application +import android.os.Bundle 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 +import com.casic.common.detector.gd.utils.GpioManager import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.SaveKeyValues import com.tencent.bugly.crashreport.CrashReport import java.io.File import java.io.IOException import java.security.InvalidParameterException +import java.util.concurrent.atomic.AtomicInteger import kotlin.properties.Delegates -class BaseApplication : Application() { +class BaseApplication : Application(), Application.ActivityLifecycleCallbacks { private val kTag = "BaseApplication" private var serialPorts = ArrayList() + private var activityReferences = 0 + private var isActivityChangingConfigurations = false + private val gpioManager by lazy { GpioManager() } + + /** + * 读取数据 1 + * 暂停读取 0 + * */ + private val gpioState = AtomicInteger(0) fun getSerialPorts(): ArrayList = serialPorts @@ -49,7 +62,6 @@ try { serialPorts.apply { add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) - add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) //千寻报文数据下发串口号 add(SerialPort(File("/dev/ttyS1"), 9600, 0)) } @@ -61,9 +73,67 @@ } catch (e: InvalidParameterException) { "请检查串口!".show(this) } + + registerActivityLifecycleCallbacks(this) } fun getDaoSession(): DaoSession { return daoSession } + + override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { + + } + + override fun onActivityStarted(activity: Activity) { + if (++activityReferences == 1 && !isActivityChangingConfigurations) { + onAppForeground() + } + } + + override fun onActivityResumed(activity: Activity) { + + } + + override fun onActivityPaused(activity: Activity) { + + } + + override fun onActivityStopped(activity: Activity) { + isActivityChangingConfigurations = activity.isChangingConfigurations + if (--activityReferences == 0 && !isActivityChangingConfigurations) { + onAppBackground() + } + } + + override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) { + + } + + override fun onActivityDestroyed(activity: Activity) { + + } + + private fun onAppForeground() { + Log.d(kTag, "onAppForeground: 处于前台") + if (gpioState.get() != 1) { + gpioManager.setGpioHigh("18") + gpioState.set(1) + Log.d(kTag, "调高串口电位") + } else { + Log.d(kTag, "已经是高电位,直接读数据") + } + } + + private fun onAppBackground() { + Log.d(kTag, "onAppBackground: 退到后台") + if (gpioState.get() == 0) { + Log.d(kTag, "已经是低电位,不响应") + return + } + // 降低串口电位 + gpioManager.setGpioLow("18") + gpioState.set(0) + Log.d(kTag, "降低串口电位") + } } \ No newline at end of file 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 deleted file mode 100644 index 08b3e19..0000000 --- a/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt +++ /dev/null @@ -1,204 +0,0 @@ -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/base/SerialPortBaseActivity.kt b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortBaseActivity.kt new file mode 100644 index 0000000..b6eeab5 --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortBaseActivity.kt @@ -0,0 +1,139 @@ +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.extensions.toBuryDepth +import com.casic.common.detector.gd.extensions.toMarkerId +import com.casic.common.detector.gd.extensions.toSignalStrength +import com.casic.common.detector.gd.utils.CurrentSegment +import com.casic.common.detector.gd.utils.RuntimeCache +import com.casic.common.detector.gd.utils.SerialPortCommand +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import java.io.IOException +import java.util.Timer + +abstract class SerialPortBaseActivity : AppCompatActivity(), Handler.Callback { + + private val kTag = "SerialPortBaseActivity" + private val taskTimer by lazy { Timer() } + private val weakReferenceHandler by lazy { WeakReferenceHandler(this) } + + //输出流 + private val outStream by lazy { BaseApplication.get().getSerialPorts()[0].outputStream } + + //输入流 + private val inStream by lazy { BaseApplication.get().getSerialPorts()[0].inputStream } + + 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 = inStream.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 onMarkerIdDetected(markerId: String) + + abstract fun onMarkerDepthDetected(depth: Int) + + abstract fun onMarkerSignalDetected(signalEnergy: Int) + + override fun handleMessage(msg: Message): Boolean { + if (msg.what == 2025012001) { + val buffer = msg.obj as ByteArray + Log.d(kTag, "${RuntimeCache.currentSegment} ${buffer.contentToString()}") + val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase() + if (RuntimeCache.currentSegment == CurrentSegment.InstallMarker && flag == "30" && buffer.size == 10) { + onMarkerIdDetected(buffer.toMarkerId()) + } else if (RuntimeCache.currentSegment == CurrentSegment.FreeInspection) { + if (flag == "30" && buffer.size == 10) { + onMarkerIdDetected(buffer.toMarkerId()) + } else if (flag == "4E" && buffer.size == 5) { + onMarkerSignalDetected(buffer.toSignalStrength()) + } + } else if (RuntimeCache.currentSegment == CurrentSegment.SearchMarker) { + if (flag == "30" && buffer.size == 10) { + onMarkerIdDetected(buffer.toMarkerId()) + } else if (flag == "4E" && buffer.size == 5) { + onMarkerSignalDetected(buffer.toSignalStrength()) + } + } else if (RuntimeCache.currentSegment == CurrentSegment.DetectDepth) { + if (flag == "53" && buffer.size == 5) { + onMarkerDepthDetected(buffer.toBuryDepth()) + } + } + } + return true + } + + fun sendSerialPortCommand(command: Int) { + outStream.write(command) + outStream.flush() + Log.d(kTag, "sendSerialPortCommand: $command") + } + + /** + * 停止串口数据传输 + * */ + fun stopSerialPortCommand() { + outStream.write(SerialPortCommand.STOP_SERIAL_PORT_DATA) + outStream.flush() + } + + override fun onDestroy() { + super.onDestroy() + stopSerialPortCommand() + } +} \ 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 5c3ee01..6994136 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 @@ -22,6 +22,7 @@ * * [48, 48, 48, 56, 56, 57, 49, 48, 55, 51] * + * 只从串口:/dev/ttysWK1 出来 * */ fun ByteArray.toMarkerId(): String { val id = this.map { it.toInt().toChar() }.joinToString("") 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 new file mode 100644 index 0000000..104f971 --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt @@ -0,0 +1,5 @@ +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/utils/SerialPortCommand.kt b/app/src/main/java/com/casic/common/detector/gd/utils/SerialPortCommand.kt new file mode 100644 index 0000000..8db2785 --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/utils/SerialPortCommand.kt @@ -0,0 +1,31 @@ +package com.casic.common.detector.gd.utils + +object SerialPortCommand { + /** + * 发送一次指令,会返回2次设备ID + * */ + const val SEARCH_MARKER_ONCE = '1'.code + + /** + * 发送一次指令,会不停的返回设备ID + * */ + const val SEARCH_MARKER_ALWAYS = '2'.code + + /** + * 串口停止发送数据 + * 3/4/5均可 + * */ + const val STOP_SERIAL_PORT_DATA = '3'.code + + /** + * 发送一次指令,会不停的返回信号强度(电磁感应) + * */ + const val SEARCH_SIGNAL = '6'.code + + /** + * 探测深度,均为一次性的,且测距会把[SEARCH_SIGNAL]和[SEARCH_MARKER_ALWAYS]中断 + * */ + const val DETECT_EM30_DEPTH = '7'.code + const val DETECT_EM50_DEPTH = '8'.code + const val DETECT_EM14_DEPTH = '9'.code +} \ 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 b3dce3c..fc795c6 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 @@ -13,7 +13,7 @@ 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.base.SerialPortBaseActivity import com.casic.common.detector.gd.bean.MarkerLocalBean import com.casic.common.detector.gd.callback.OnGetLocationListener import com.casic.common.detector.gd.callback.OnImageCompressListener @@ -24,12 +24,13 @@ import com.casic.common.detector.gd.extensions.setDefaultValue import com.casic.common.detector.gd.extensions.show 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.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.utils.SerialPortCommand import com.casic.common.detector.gd.vm.TaskViewModel import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType @@ -50,7 +51,7 @@ import java.util.Calendar import java.util.Date -class InstallMarkerActivity : SerialPortActivity() { +class InstallMarkerActivity : SerialPortBaseActivity() { private val kTag = "InstallMarkerActivity" private val context = this @@ -243,27 +244,29 @@ //读标识器 binding.readMarkerButton.setOnClickListener { - openSerialPort() - LoadingDialog.show(this, "标识器读取中,请稍后...") + RuntimeCache.currentSegment = CurrentSegment.InstallMarker countDownTimer.start() binding.readMarkerButton.isEnabled = false - readMarkerId() + sendSerialPortCommand(SerialPortCommand.SEARCH_MARKER_ALWAYS) } } - 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() - binding.readMarkerButton.isEnabled = true - binding.identifierInclude.identifierIdView.text = markerId - } + override fun onMarkerIdDetected(markerId: String) { + if (RuntimeCache.currentSegment == CurrentSegment.InstallMarker) { + countDownTimer.cancel() + binding.readMarkerButton.isEnabled = true + binding.identifierInclude.identifierIdView.text = markerId } } + override fun onMarkerDepthDetected(depth: Int) { + + } + + override fun onMarkerSignalDetected(signalEnergy: Int) { + + } + /** * 搜索标识器超时倒计时 * */ @@ -273,7 +276,6 @@ } override fun onFinish() { - LoadingDialog.dismiss() "读取此标识器ID超时,请重试".show(context) binding.readMarkerButton.isEnabled = true } 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 e5fe1f5..7b695ff 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,22 +1,35 @@ package com.casic.common.detector.gd.base +import android.app.Activity import android.app.Application +import android.os.Bundle 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 +import com.casic.common.detector.gd.utils.GpioManager import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.SaveKeyValues import com.tencent.bugly.crashreport.CrashReport import java.io.File import java.io.IOException import java.security.InvalidParameterException +import java.util.concurrent.atomic.AtomicInteger import kotlin.properties.Delegates -class BaseApplication : Application() { +class BaseApplication : Application(), Application.ActivityLifecycleCallbacks { private val kTag = "BaseApplication" private var serialPorts = ArrayList() + private var activityReferences = 0 + private var isActivityChangingConfigurations = false + private val gpioManager by lazy { GpioManager() } + + /** + * 读取数据 1 + * 暂停读取 0 + * */ + private val gpioState = AtomicInteger(0) fun getSerialPorts(): ArrayList = serialPorts @@ -49,7 +62,6 @@ try { serialPorts.apply { add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) - add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) //千寻报文数据下发串口号 add(SerialPort(File("/dev/ttyS1"), 9600, 0)) } @@ -61,9 +73,67 @@ } catch (e: InvalidParameterException) { "请检查串口!".show(this) } + + registerActivityLifecycleCallbacks(this) } fun getDaoSession(): DaoSession { return daoSession } + + override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { + + } + + override fun onActivityStarted(activity: Activity) { + if (++activityReferences == 1 && !isActivityChangingConfigurations) { + onAppForeground() + } + } + + override fun onActivityResumed(activity: Activity) { + + } + + override fun onActivityPaused(activity: Activity) { + + } + + override fun onActivityStopped(activity: Activity) { + isActivityChangingConfigurations = activity.isChangingConfigurations + if (--activityReferences == 0 && !isActivityChangingConfigurations) { + onAppBackground() + } + } + + override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) { + + } + + override fun onActivityDestroyed(activity: Activity) { + + } + + private fun onAppForeground() { + Log.d(kTag, "onAppForeground: 处于前台") + if (gpioState.get() != 1) { + gpioManager.setGpioHigh("18") + gpioState.set(1) + Log.d(kTag, "调高串口电位") + } else { + Log.d(kTag, "已经是高电位,直接读数据") + } + } + + private fun onAppBackground() { + Log.d(kTag, "onAppBackground: 退到后台") + if (gpioState.get() == 0) { + Log.d(kTag, "已经是低电位,不响应") + return + } + // 降低串口电位 + gpioManager.setGpioLow("18") + gpioState.set(0) + Log.d(kTag, "降低串口电位") + } } \ No newline at end of file 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 deleted file mode 100644 index 08b3e19..0000000 --- a/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt +++ /dev/null @@ -1,204 +0,0 @@ -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/base/SerialPortBaseActivity.kt b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortBaseActivity.kt new file mode 100644 index 0000000..b6eeab5 --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortBaseActivity.kt @@ -0,0 +1,139 @@ +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.extensions.toBuryDepth +import com.casic.common.detector.gd.extensions.toMarkerId +import com.casic.common.detector.gd.extensions.toSignalStrength +import com.casic.common.detector.gd.utils.CurrentSegment +import com.casic.common.detector.gd.utils.RuntimeCache +import com.casic.common.detector.gd.utils.SerialPortCommand +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import java.io.IOException +import java.util.Timer + +abstract class SerialPortBaseActivity : AppCompatActivity(), Handler.Callback { + + private val kTag = "SerialPortBaseActivity" + private val taskTimer by lazy { Timer() } + private val weakReferenceHandler by lazy { WeakReferenceHandler(this) } + + //输出流 + private val outStream by lazy { BaseApplication.get().getSerialPorts()[0].outputStream } + + //输入流 + private val inStream by lazy { BaseApplication.get().getSerialPorts()[0].inputStream } + + 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 = inStream.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 onMarkerIdDetected(markerId: String) + + abstract fun onMarkerDepthDetected(depth: Int) + + abstract fun onMarkerSignalDetected(signalEnergy: Int) + + override fun handleMessage(msg: Message): Boolean { + if (msg.what == 2025012001) { + val buffer = msg.obj as ByteArray + Log.d(kTag, "${RuntimeCache.currentSegment} ${buffer.contentToString()}") + val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase() + if (RuntimeCache.currentSegment == CurrentSegment.InstallMarker && flag == "30" && buffer.size == 10) { + onMarkerIdDetected(buffer.toMarkerId()) + } else if (RuntimeCache.currentSegment == CurrentSegment.FreeInspection) { + if (flag == "30" && buffer.size == 10) { + onMarkerIdDetected(buffer.toMarkerId()) + } else if (flag == "4E" && buffer.size == 5) { + onMarkerSignalDetected(buffer.toSignalStrength()) + } + } else if (RuntimeCache.currentSegment == CurrentSegment.SearchMarker) { + if (flag == "30" && buffer.size == 10) { + onMarkerIdDetected(buffer.toMarkerId()) + } else if (flag == "4E" && buffer.size == 5) { + onMarkerSignalDetected(buffer.toSignalStrength()) + } + } else if (RuntimeCache.currentSegment == CurrentSegment.DetectDepth) { + if (flag == "53" && buffer.size == 5) { + onMarkerDepthDetected(buffer.toBuryDepth()) + } + } + } + return true + } + + fun sendSerialPortCommand(command: Int) { + outStream.write(command) + outStream.flush() + Log.d(kTag, "sendSerialPortCommand: $command") + } + + /** + * 停止串口数据传输 + * */ + fun stopSerialPortCommand() { + outStream.write(SerialPortCommand.STOP_SERIAL_PORT_DATA) + outStream.flush() + } + + override fun onDestroy() { + super.onDestroy() + stopSerialPortCommand() + } +} \ 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 5c3ee01..6994136 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 @@ -22,6 +22,7 @@ * * [48, 48, 48, 56, 56, 57, 49, 48, 55, 51] * + * 只从串口:/dev/ttysWK1 出来 * */ fun ByteArray.toMarkerId(): String { val id = this.map { it.toInt().toChar() }.joinToString("") 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 new file mode 100644 index 0000000..104f971 --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt @@ -0,0 +1,5 @@ +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/utils/SerialPortCommand.kt b/app/src/main/java/com/casic/common/detector/gd/utils/SerialPortCommand.kt new file mode 100644 index 0000000..8db2785 --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/utils/SerialPortCommand.kt @@ -0,0 +1,31 @@ +package com.casic.common.detector.gd.utils + +object SerialPortCommand { + /** + * 发送一次指令,会返回2次设备ID + * */ + const val SEARCH_MARKER_ONCE = '1'.code + + /** + * 发送一次指令,会不停的返回设备ID + * */ + const val SEARCH_MARKER_ALWAYS = '2'.code + + /** + * 串口停止发送数据 + * 3/4/5均可 + * */ + const val STOP_SERIAL_PORT_DATA = '3'.code + + /** + * 发送一次指令,会不停的返回信号强度(电磁感应) + * */ + const val SEARCH_SIGNAL = '6'.code + + /** + * 探测深度,均为一次性的,且测距会把[SEARCH_SIGNAL]和[SEARCH_MARKER_ALWAYS]中断 + * */ + const val DETECT_EM30_DEPTH = '7'.code + const val DETECT_EM50_DEPTH = '8'.code + const val DETECT_EM14_DEPTH = '9'.code +} \ 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 b3dce3c..fc795c6 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 @@ -13,7 +13,7 @@ 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.base.SerialPortBaseActivity import com.casic.common.detector.gd.bean.MarkerLocalBean import com.casic.common.detector.gd.callback.OnGetLocationListener import com.casic.common.detector.gd.callback.OnImageCompressListener @@ -24,12 +24,13 @@ import com.casic.common.detector.gd.extensions.setDefaultValue import com.casic.common.detector.gd.extensions.show 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.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.utils.SerialPortCommand import com.casic.common.detector.gd.vm.TaskViewModel import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType @@ -50,7 +51,7 @@ import java.util.Calendar import java.util.Date -class InstallMarkerActivity : SerialPortActivity() { +class InstallMarkerActivity : SerialPortBaseActivity() { private val kTag = "InstallMarkerActivity" private val context = this @@ -243,27 +244,29 @@ //读标识器 binding.readMarkerButton.setOnClickListener { - openSerialPort() - LoadingDialog.show(this, "标识器读取中,请稍后...") + RuntimeCache.currentSegment = CurrentSegment.InstallMarker countDownTimer.start() binding.readMarkerButton.isEnabled = false - readMarkerId() + sendSerialPortCommand(SerialPortCommand.SEARCH_MARKER_ALWAYS) } } - 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() - binding.readMarkerButton.isEnabled = true - binding.identifierInclude.identifierIdView.text = markerId - } + override fun onMarkerIdDetected(markerId: String) { + if (RuntimeCache.currentSegment == CurrentSegment.InstallMarker) { + countDownTimer.cancel() + binding.readMarkerButton.isEnabled = true + binding.identifierInclude.identifierIdView.text = markerId } } + override fun onMarkerDepthDetected(depth: Int) { + + } + + override fun onMarkerSignalDetected(signalEnergy: Int) { + + } + /** * 搜索标识器超时倒计时 * */ @@ -273,7 +276,6 @@ } override fun onFinish() { - LoadingDialog.dismiss() "读取此标识器ID超时,请重试".show(context) binding.readMarkerButton.isEnabled = true } 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 5417e1f..83eeee3 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,5 +1,6 @@ package com.casic.common.detector.gd.view +import android.content.res.ColorStateList import android.graphics.Color import android.hardware.Sensor import android.hardware.SensorEvent @@ -8,27 +9,25 @@ import android.media.AudioAttributes import android.media.SoundPool import android.os.Bundle -import android.os.CountDownTimer -import android.util.Log +import android.os.Handler +import android.os.Looper import android.view.View -import android.view.WindowManager import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import com.amap.api.location.AMapLocation 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.base.SerialPortBaseActivity 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.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.utils.SerialPortCommand import com.casic.common.detector.gd.vm.TaskViewModel import com.casic.common.detector.gd.widgets.RadarScanView import com.pengxh.kt.lite.extensions.getSystemService @@ -41,11 +40,9 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import java.util.Timer -import java.util.TimerTask import kotlin.math.atan2 -class SearchMarkerActivity : SerialPortActivity(), +class SearchMarkerActivity : SerialPortBaseActivity(), SensorEventListener { private val kTag = "SearchMarkerActivity" @@ -63,11 +60,11 @@ private var fastSoundResourceId = 0 private var markerId = ""//标识器ID private var isExecuteTask = false - private var signalEnergy = 0 //标识器信号强度 private var gravity: FloatArray? = null private var geomagnetic: FloatArray? = null override fun initOnCreate(savedInstanceState: Bundle?) { + RuntimeCache.currentSegment = CurrentSegment.SearchMarker val taskState = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY) as String isExecuteTask = taskState != "0" @@ -93,151 +90,138 @@ binding.taskStateView.isSelected = true } - openSerialPort() - searchMarker(CurrentSegment.SearchMarker) + //进入界面开始搜索信号强度 + sendSerialPortCommand(SerialPortCommand.SEARCH_SIGNAL) + } - //在标识器信号强度很强的时候,从数据库中计算出距离最近的点,以防出现探测不到ID的情况 - Timer().schedule(object : TimerTask() { - override fun run() { - if (signalEnergy <= 700) {//18° - runOnUiThread { - binding.energyTipsView.text = "信号较弱,可能距离较远" - binding.energyTipsView.setTextColor(Color.parseColor("#8D1717")) - binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_red) + private val handler = Handler(Looper.getMainLooper()) + private var detectDepthRunnable: DetectDepthRunnable? = null - binding.depthButton.isEnabled = false - binding.depthButton.setTextColor(Color.parseColor("#CCCCCC")) - binding.depthButton.setBackgroundResource(R.mipmap.left_button_disable) - binding.markerInfoButton.isEnabled = false - binding.markerInfoButton.setTextColor(Color.parseColor("#CCCCCC")) - binding.markerInfoButton.setBackgroundResource(R.mipmap.right_button_disable) - - binding.searchResultView.text = "未检测到标识器" - binding.searchResultView.setTextColor(Color.parseColor("#8D1717")) - binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_red) - } - } else if (signalEnergy >= 4100 && markerPoints.isNotEmpty()) { - //markerId为空,说明没有通过探测得到标识器ID,那么就需要通过计算得到近似的标识器 - try { - //需要转一下,不然会有并发问题 - val temp = ArrayList() - temp.addAll(markerPoints) - temp.sortBy(MarkerDistanceData::distance) - val nearestPoint = temp.first() - runOnUiThread { - handleMarker(nearestPoint.markerId) - } - markerPoints.clear() - } catch (e: NullPointerException) { - e.printStackTrace() - } - } else { - runOnUiThread { - binding.energyTipsView.text = "已靠近,请继续移动位置" - binding.energyTipsView.setTextColor(Color.parseColor("#8C5700")) - binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_yellow) - } - } - } - }, 0, 2000) + private inner class DetectDepthRunnable(private val command: Int) : Runnable { + override fun run() { + sendSerialPortCommand(command) + //延迟三秒再发一次 + handler.postDelayed(this, 3000) + } } override fun initEvent() { binding.depthButton.setOnClickListener { + RuntimeCache.currentSegment = CurrentSegment.DetectDepth val result = DataBaseManager.get.queryMarkerById(markerId) if (result.isNotEmpty()) { - val tag = when (result.first().markerType) { - "EM30" -> '7' - "EM50" -> '8' - "EM14" -> '9' - else -> '1' + val command = when (result.first().markerType) { + "EM30" -> SerialPortCommand.DETECT_EM30_DEPTH + "EM50" -> SerialPortCommand.DETECT_EM50_DEPTH + "EM14" -> SerialPortCommand.DETECT_EM14_DEPTH + else -> SerialPortCommand.STOP_SERIAL_PORT_DATA } - if (tag == '1') { + if (command == SerialPortCommand.STOP_SERIAL_PORT_DATA) { "此标识器无法读取埋深!".show(this) } else { soundPool.autoPause() LoadingDialog.show(this, "正在探测标识器埋深,请稍后...") + + // 移除之前的 Runnable(如果存在) + detectDepthRunnable?.let { handler.removeCallbacks(it) } + detectDepthRunnable = DetectDepthRunnable(command) // 发送读取标识器埋设深度指令 - detectDepth(tag) - object : CountDownTimer(3 * 1000, 1000) { - override fun onTick(millisUntilFinished: Long) { - - } - - override fun onFinish() { - LoadingDialog.dismiss() - updateSegment(CurrentSegment.SearchMarker) - } - }.start() + handler.post(detectDepthRunnable!!) } } else { - LoadingDialog.dismiss() "标识器未安装,安装成功后才可读取埋深!".show(this) } } + binding.markerIdButton.setOnClickListener { + sendSerialPortCommand(SerialPortCommand.SEARCH_MARKER_ALWAYS) + } + binding.markerInfoButton.setOnClickListener { - //查库 val result = DataBaseManager.get.queryMarkerById(markerId) if (result.isNotEmpty()) { navigatePageTo(markerId) } else { navigatePageTo(markerId) } - //查看完就把ID置空,便于下次查看最新的ID markerId = "" } } - 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() - try { - AlertMessageDialog.Builder().setContext(context) - .setTitle("温馨提示") - .setMessage("标识器埋深:${buffer.toBuryDepth()}厘米") - .setPositiveButton("知道了") - .setOnDialogButtonClickListener(object : - AlertMessageDialog.OnDialogButtonClickListener { - override fun onConfirmClick() { - updateSegment(CurrentSegment.SearchMarker) - } - }).build().show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } 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() + override fun onMarkerIdDetected(markerId: String) { + if (RuntimeCache.currentSegment == CurrentSegment.SearchMarker) { + binding.depthButton.isEnabled = true + binding.depthButton.setTextColor(Color.WHITE) + binding.depthButton.backgroundTintList = + ColorStateList.valueOf(Color.parseColor("#004364")) - //声音 - updateSound(signalEnergy) + binding.markerInfoButton.isEnabled = true + binding.markerInfoButton.setTextColor(Color.WHITE) + binding.markerInfoButton.backgroundTintList = + ColorStateList.valueOf(Color.parseColor("#FFA200")) - //信号强度显示 - updateProgressBar(signalEnergy) + handleMarker(markerId) + } + } - //搜索信号文字显示 - updateTextResult(signalEnergy) - } else { - Log.d(kTag, "乱码数据: ${buffer.contentToString()}") + private fun handleMarker(id: String) { + this.markerId = id + //自动上传标识器 + if (isExecuteTask) { + val taskId = SaveKeyValues.getValue(LocaleConstant.TASK_ID, "") as String + val taskCode = SaveKeyValues.getValue(LocaleConstant.TASK_CODE, "") as String + val taskMarkerLocalBean = DataBaseManager.get.queryTaskMarkerById( + taskId, taskCode, id, "0" + ) + taskMarkerLocalBean?.apply { + taskViewModel.uploadMarker(context, this) } } } - private fun updateSound(signalEnergy: Int) { - val soundResourceId = if (signalEnergy >= 4000) fastSoundResourceId else slowSoundResourceId - soundPool.play(soundResourceId, 1f, 1f, 0, 0, 1f) + override fun onMarkerDepthDetected(depth: Int) { + if (RuntimeCache.currentSegment == CurrentSegment.DetectDepth) { + detectDepthRunnable?.let { handler.removeCallbacks(it) } + detectDepthRunnable = null + LoadingDialog.dismiss() + AlertMessageDialog.Builder().setContext(context).setTitle("温馨提示") + .setMessage("标识器埋深:${depth}厘米").setPositiveButton("知道了") + .setOnDialogButtonClickListener(object : + AlertMessageDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + RuntimeCache.currentSegment = CurrentSegment.SearchMarker + sendSerialPortCommand(SerialPortCommand.SEARCH_SIGNAL) + } + }).build().show() + } } - private fun updateProgressBar(signalEnergy: Int) { - binding.energyPgBar.progress = signalEnergy - binding.energyValueView.text = "${signalEnergy}dB" + override fun onMarkerSignalDetected(signalEnergy: Int) { + if (RuntimeCache.currentSegment == CurrentSegment.SearchMarker) { + if (signalEnergy > 1000) { + binding.markerIdButton.isEnabled = true + binding.markerIdButton.setTextColor(Color.WHITE) + binding.markerIdButton.backgroundTintList = ColorStateList.valueOf( + Color.parseColor("#FFA200") + ) + + binding.searchResultView.text = "已检测到标识器" + binding.searchResultView.setTextColor(Color.parseColor("#428d00")) + binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_green) + } + + //声音 + val soundResourceId = if (signalEnergy >= 4000) + fastSoundResourceId else slowSoundResourceId + soundPool.play(soundResourceId, 1f, 1f, 0, 0, 1f) + + //信号强度显示 + binding.energyPgBar.progress = signalEnergy + binding.energyValueView.text = "${signalEnergy}dB" + + //搜索信号文字显示 + updateTextResult(signalEnergy) + } } private fun updateTextResult(signalEnergy: Int) { @@ -278,13 +262,19 @@ binding.energyTipsView.setBackgroundResource(backgroundRes) } + private val colorStateList = ColorStateList.valueOf(Color.parseColor("#8A8A8A")) + private val textColor = Color.parseColor("#CCCCCC") + private fun disableButtons() { binding.depthButton.isEnabled = false - binding.depthButton.setTextColor(Color.parseColor("#CCCCCC")) - binding.depthButton.setBackgroundResource(R.mipmap.left_button_disable) + binding.depthButton.setTextColor(textColor) + binding.depthButton.backgroundTintList = colorStateList + binding.markerIdButton.isEnabled = false + binding.markerIdButton.setTextColor(textColor) + binding.markerIdButton.backgroundTintList = colorStateList binding.markerInfoButton.isEnabled = false - binding.markerInfoButton.setTextColor(Color.parseColor("#CCCCCC")) - binding.markerInfoButton.setBackgroundResource(R.mipmap.right_button_disable) + binding.markerInfoButton.setTextColor(textColor) + binding.markerInfoButton.backgroundTintList = colorStateList } /** @@ -315,7 +305,8 @@ } } withContext(Dispatchers.Main) { - binding.radarScanView.renderPointData(dataPoints, + binding.radarScanView.renderPointData( + dataPoints, object : RadarScanView.OnGetNearestPointCallback { override fun getNearestPoint(point: RadarScanView.DataPoint?) { if (point == null) { @@ -331,8 +322,7 @@ binding.distancePgBar.progress = progress.toInt() } } - } - ) + }) } } } @@ -349,33 +339,6 @@ } - private fun handleMarker(id: String) { - this.markerId = id - - binding.depthButton.isEnabled = true - binding.depthButton.setTextColor(Color.WHITE) - binding.depthButton.setBackgroundResource(R.mipmap.left_button_enable) - binding.markerInfoButton.isEnabled = true - binding.markerInfoButton.setTextColor(Color.WHITE) - binding.markerInfoButton.setBackgroundResource(R.mipmap.right_button_enable) - - binding.searchResultView.text = "已检测到标识器" - binding.searchResultView.setTextColor(Color.parseColor("#428d00")) - binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_green) - - //自动上传标识器 - if (isExecuteTask) { - val taskId = SaveKeyValues.getValue(LocaleConstant.TASK_ID, "") as String - val taskCode = SaveKeyValues.getValue(LocaleConstant.TASK_CODE, "") as String - val taskMarkerLocalBean = DataBaseManager.get.queryTaskMarkerById( - taskId, taskCode, id, "0" - ) - taskMarkerLocalBean?.apply { - taskViewModel.uploadMarker(context, this) - } - } - } - override fun onResume() { super.onResume() //注册加速度传感器监听 @@ -421,7 +384,6 @@ override fun onDestroy() { super.onDestroy() - closeSerialPort() soundPool.autoPause() locationKit.stopLocation() } 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 e5fe1f5..7b695ff 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,22 +1,35 @@ package com.casic.common.detector.gd.base +import android.app.Activity import android.app.Application +import android.os.Bundle 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 +import com.casic.common.detector.gd.utils.GpioManager import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.SaveKeyValues import com.tencent.bugly.crashreport.CrashReport import java.io.File import java.io.IOException import java.security.InvalidParameterException +import java.util.concurrent.atomic.AtomicInteger import kotlin.properties.Delegates -class BaseApplication : Application() { +class BaseApplication : Application(), Application.ActivityLifecycleCallbacks { private val kTag = "BaseApplication" private var serialPorts = ArrayList() + private var activityReferences = 0 + private var isActivityChangingConfigurations = false + private val gpioManager by lazy { GpioManager() } + + /** + * 读取数据 1 + * 暂停读取 0 + * */ + private val gpioState = AtomicInteger(0) fun getSerialPorts(): ArrayList = serialPorts @@ -49,7 +62,6 @@ try { serialPorts.apply { add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) - add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) //千寻报文数据下发串口号 add(SerialPort(File("/dev/ttyS1"), 9600, 0)) } @@ -61,9 +73,67 @@ } catch (e: InvalidParameterException) { "请检查串口!".show(this) } + + registerActivityLifecycleCallbacks(this) } fun getDaoSession(): DaoSession { return daoSession } + + override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { + + } + + override fun onActivityStarted(activity: Activity) { + if (++activityReferences == 1 && !isActivityChangingConfigurations) { + onAppForeground() + } + } + + override fun onActivityResumed(activity: Activity) { + + } + + override fun onActivityPaused(activity: Activity) { + + } + + override fun onActivityStopped(activity: Activity) { + isActivityChangingConfigurations = activity.isChangingConfigurations + if (--activityReferences == 0 && !isActivityChangingConfigurations) { + onAppBackground() + } + } + + override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) { + + } + + override fun onActivityDestroyed(activity: Activity) { + + } + + private fun onAppForeground() { + Log.d(kTag, "onAppForeground: 处于前台") + if (gpioState.get() != 1) { + gpioManager.setGpioHigh("18") + gpioState.set(1) + Log.d(kTag, "调高串口电位") + } else { + Log.d(kTag, "已经是高电位,直接读数据") + } + } + + private fun onAppBackground() { + Log.d(kTag, "onAppBackground: 退到后台") + if (gpioState.get() == 0) { + Log.d(kTag, "已经是低电位,不响应") + return + } + // 降低串口电位 + gpioManager.setGpioLow("18") + gpioState.set(0) + Log.d(kTag, "降低串口电位") + } } \ No newline at end of file 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 deleted file mode 100644 index 08b3e19..0000000 --- a/app/src/main/java/com/casic/common/detector/gd/base/SerialPortActivity.kt +++ /dev/null @@ -1,204 +0,0 @@ -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/base/SerialPortBaseActivity.kt b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortBaseActivity.kt new file mode 100644 index 0000000..b6eeab5 --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/base/SerialPortBaseActivity.kt @@ -0,0 +1,139 @@ +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.extensions.toBuryDepth +import com.casic.common.detector.gd.extensions.toMarkerId +import com.casic.common.detector.gd.extensions.toSignalStrength +import com.casic.common.detector.gd.utils.CurrentSegment +import com.casic.common.detector.gd.utils.RuntimeCache +import com.casic.common.detector.gd.utils.SerialPortCommand +import com.pengxh.kt.lite.utils.WeakReferenceHandler +import java.io.IOException +import java.util.Timer + +abstract class SerialPortBaseActivity : AppCompatActivity(), Handler.Callback { + + private val kTag = "SerialPortBaseActivity" + private val taskTimer by lazy { Timer() } + private val weakReferenceHandler by lazy { WeakReferenceHandler(this) } + + //输出流 + private val outStream by lazy { BaseApplication.get().getSerialPorts()[0].outputStream } + + //输入流 + private val inStream by lazy { BaseApplication.get().getSerialPorts()[0].inputStream } + + 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 = inStream.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 onMarkerIdDetected(markerId: String) + + abstract fun onMarkerDepthDetected(depth: Int) + + abstract fun onMarkerSignalDetected(signalEnergy: Int) + + override fun handleMessage(msg: Message): Boolean { + if (msg.what == 2025012001) { + val buffer = msg.obj as ByteArray + Log.d(kTag, "${RuntimeCache.currentSegment} ${buffer.contentToString()}") + val flag = (buffer.first().toInt() and 0xFF).toString(16).uppercase() + if (RuntimeCache.currentSegment == CurrentSegment.InstallMarker && flag == "30" && buffer.size == 10) { + onMarkerIdDetected(buffer.toMarkerId()) + } else if (RuntimeCache.currentSegment == CurrentSegment.FreeInspection) { + if (flag == "30" && buffer.size == 10) { + onMarkerIdDetected(buffer.toMarkerId()) + } else if (flag == "4E" && buffer.size == 5) { + onMarkerSignalDetected(buffer.toSignalStrength()) + } + } else if (RuntimeCache.currentSegment == CurrentSegment.SearchMarker) { + if (flag == "30" && buffer.size == 10) { + onMarkerIdDetected(buffer.toMarkerId()) + } else if (flag == "4E" && buffer.size == 5) { + onMarkerSignalDetected(buffer.toSignalStrength()) + } + } else if (RuntimeCache.currentSegment == CurrentSegment.DetectDepth) { + if (flag == "53" && buffer.size == 5) { + onMarkerDepthDetected(buffer.toBuryDepth()) + } + } + } + return true + } + + fun sendSerialPortCommand(command: Int) { + outStream.write(command) + outStream.flush() + Log.d(kTag, "sendSerialPortCommand: $command") + } + + /** + * 停止串口数据传输 + * */ + fun stopSerialPortCommand() { + outStream.write(SerialPortCommand.STOP_SERIAL_PORT_DATA) + outStream.flush() + } + + override fun onDestroy() { + super.onDestroy() + stopSerialPortCommand() + } +} \ 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 5c3ee01..6994136 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 @@ -22,6 +22,7 @@ * * [48, 48, 48, 56, 56, 57, 49, 48, 55, 51] * + * 只从串口:/dev/ttysWK1 出来 * */ fun ByteArray.toMarkerId(): String { val id = this.map { it.toInt().toChar() }.joinToString("") 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 new file mode 100644 index 0000000..104f971 --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/utils/RuntimeCache.kt @@ -0,0 +1,5 @@ +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/utils/SerialPortCommand.kt b/app/src/main/java/com/casic/common/detector/gd/utils/SerialPortCommand.kt new file mode 100644 index 0000000..8db2785 --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/utils/SerialPortCommand.kt @@ -0,0 +1,31 @@ +package com.casic.common.detector.gd.utils + +object SerialPortCommand { + /** + * 发送一次指令,会返回2次设备ID + * */ + const val SEARCH_MARKER_ONCE = '1'.code + + /** + * 发送一次指令,会不停的返回设备ID + * */ + const val SEARCH_MARKER_ALWAYS = '2'.code + + /** + * 串口停止发送数据 + * 3/4/5均可 + * */ + const val STOP_SERIAL_PORT_DATA = '3'.code + + /** + * 发送一次指令,会不停的返回信号强度(电磁感应) + * */ + const val SEARCH_SIGNAL = '6'.code + + /** + * 探测深度,均为一次性的,且测距会把[SEARCH_SIGNAL]和[SEARCH_MARKER_ALWAYS]中断 + * */ + const val DETECT_EM30_DEPTH = '7'.code + const val DETECT_EM50_DEPTH = '8'.code + const val DETECT_EM14_DEPTH = '9'.code +} \ 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 b3dce3c..fc795c6 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 @@ -13,7 +13,7 @@ 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.base.SerialPortBaseActivity import com.casic.common.detector.gd.bean.MarkerLocalBean import com.casic.common.detector.gd.callback.OnGetLocationListener import com.casic.common.detector.gd.callback.OnImageCompressListener @@ -24,12 +24,13 @@ import com.casic.common.detector.gd.extensions.setDefaultValue import com.casic.common.detector.gd.extensions.show 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.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.utils.SerialPortCommand import com.casic.common.detector.gd.vm.TaskViewModel import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType @@ -50,7 +51,7 @@ import java.util.Calendar import java.util.Date -class InstallMarkerActivity : SerialPortActivity() { +class InstallMarkerActivity : SerialPortBaseActivity() { private val kTag = "InstallMarkerActivity" private val context = this @@ -243,27 +244,29 @@ //读标识器 binding.readMarkerButton.setOnClickListener { - openSerialPort() - LoadingDialog.show(this, "标识器读取中,请稍后...") + RuntimeCache.currentSegment = CurrentSegment.InstallMarker countDownTimer.start() binding.readMarkerButton.isEnabled = false - readMarkerId() + sendSerialPortCommand(SerialPortCommand.SEARCH_MARKER_ALWAYS) } } - 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() - binding.readMarkerButton.isEnabled = true - binding.identifierInclude.identifierIdView.text = markerId - } + override fun onMarkerIdDetected(markerId: String) { + if (RuntimeCache.currentSegment == CurrentSegment.InstallMarker) { + countDownTimer.cancel() + binding.readMarkerButton.isEnabled = true + binding.identifierInclude.identifierIdView.text = markerId } } + override fun onMarkerDepthDetected(depth: Int) { + + } + + override fun onMarkerSignalDetected(signalEnergy: Int) { + + } + /** * 搜索标识器超时倒计时 * */ @@ -273,7 +276,6 @@ } override fun onFinish() { - LoadingDialog.dismiss() "读取此标识器ID超时,请重试".show(context) binding.readMarkerButton.isEnabled = true } 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 5417e1f..83eeee3 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,5 +1,6 @@ package com.casic.common.detector.gd.view +import android.content.res.ColorStateList import android.graphics.Color import android.hardware.Sensor import android.hardware.SensorEvent @@ -8,27 +9,25 @@ import android.media.AudioAttributes import android.media.SoundPool import android.os.Bundle -import android.os.CountDownTimer -import android.util.Log +import android.os.Handler +import android.os.Looper import android.view.View -import android.view.WindowManager import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import com.amap.api.location.AMapLocation 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.base.SerialPortBaseActivity 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.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.utils.SerialPortCommand import com.casic.common.detector.gd.vm.TaskViewModel import com.casic.common.detector.gd.widgets.RadarScanView import com.pengxh.kt.lite.extensions.getSystemService @@ -41,11 +40,9 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import java.util.Timer -import java.util.TimerTask import kotlin.math.atan2 -class SearchMarkerActivity : SerialPortActivity(), +class SearchMarkerActivity : SerialPortBaseActivity(), SensorEventListener { private val kTag = "SearchMarkerActivity" @@ -63,11 +60,11 @@ private var fastSoundResourceId = 0 private var markerId = ""//标识器ID private var isExecuteTask = false - private var signalEnergy = 0 //标识器信号强度 private var gravity: FloatArray? = null private var geomagnetic: FloatArray? = null override fun initOnCreate(savedInstanceState: Bundle?) { + RuntimeCache.currentSegment = CurrentSegment.SearchMarker val taskState = intent.getStringExtra(LiteKitConstant.INTENT_PARAM_KEY) as String isExecuteTask = taskState != "0" @@ -93,151 +90,138 @@ binding.taskStateView.isSelected = true } - openSerialPort() - searchMarker(CurrentSegment.SearchMarker) + //进入界面开始搜索信号强度 + sendSerialPortCommand(SerialPortCommand.SEARCH_SIGNAL) + } - //在标识器信号强度很强的时候,从数据库中计算出距离最近的点,以防出现探测不到ID的情况 - Timer().schedule(object : TimerTask() { - override fun run() { - if (signalEnergy <= 700) {//18° - runOnUiThread { - binding.energyTipsView.text = "信号较弱,可能距离较远" - binding.energyTipsView.setTextColor(Color.parseColor("#8D1717")) - binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_red) + private val handler = Handler(Looper.getMainLooper()) + private var detectDepthRunnable: DetectDepthRunnable? = null - binding.depthButton.isEnabled = false - binding.depthButton.setTextColor(Color.parseColor("#CCCCCC")) - binding.depthButton.setBackgroundResource(R.mipmap.left_button_disable) - binding.markerInfoButton.isEnabled = false - binding.markerInfoButton.setTextColor(Color.parseColor("#CCCCCC")) - binding.markerInfoButton.setBackgroundResource(R.mipmap.right_button_disable) - - binding.searchResultView.text = "未检测到标识器" - binding.searchResultView.setTextColor(Color.parseColor("#8D1717")) - binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_red) - } - } else if (signalEnergy >= 4100 && markerPoints.isNotEmpty()) { - //markerId为空,说明没有通过探测得到标识器ID,那么就需要通过计算得到近似的标识器 - try { - //需要转一下,不然会有并发问题 - val temp = ArrayList() - temp.addAll(markerPoints) - temp.sortBy(MarkerDistanceData::distance) - val nearestPoint = temp.first() - runOnUiThread { - handleMarker(nearestPoint.markerId) - } - markerPoints.clear() - } catch (e: NullPointerException) { - e.printStackTrace() - } - } else { - runOnUiThread { - binding.energyTipsView.text = "已靠近,请继续移动位置" - binding.energyTipsView.setTextColor(Color.parseColor("#8C5700")) - binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_yellow) - } - } - } - }, 0, 2000) + private inner class DetectDepthRunnable(private val command: Int) : Runnable { + override fun run() { + sendSerialPortCommand(command) + //延迟三秒再发一次 + handler.postDelayed(this, 3000) + } } override fun initEvent() { binding.depthButton.setOnClickListener { + RuntimeCache.currentSegment = CurrentSegment.DetectDepth val result = DataBaseManager.get.queryMarkerById(markerId) if (result.isNotEmpty()) { - val tag = when (result.first().markerType) { - "EM30" -> '7' - "EM50" -> '8' - "EM14" -> '9' - else -> '1' + val command = when (result.first().markerType) { + "EM30" -> SerialPortCommand.DETECT_EM30_DEPTH + "EM50" -> SerialPortCommand.DETECT_EM50_DEPTH + "EM14" -> SerialPortCommand.DETECT_EM14_DEPTH + else -> SerialPortCommand.STOP_SERIAL_PORT_DATA } - if (tag == '1') { + if (command == SerialPortCommand.STOP_SERIAL_PORT_DATA) { "此标识器无法读取埋深!".show(this) } else { soundPool.autoPause() LoadingDialog.show(this, "正在探测标识器埋深,请稍后...") + + // 移除之前的 Runnable(如果存在) + detectDepthRunnable?.let { handler.removeCallbacks(it) } + detectDepthRunnable = DetectDepthRunnable(command) // 发送读取标识器埋设深度指令 - detectDepth(tag) - object : CountDownTimer(3 * 1000, 1000) { - override fun onTick(millisUntilFinished: Long) { - - } - - override fun onFinish() { - LoadingDialog.dismiss() - updateSegment(CurrentSegment.SearchMarker) - } - }.start() + handler.post(detectDepthRunnable!!) } } else { - LoadingDialog.dismiss() "标识器未安装,安装成功后才可读取埋深!".show(this) } } + binding.markerIdButton.setOnClickListener { + sendSerialPortCommand(SerialPortCommand.SEARCH_MARKER_ALWAYS) + } + binding.markerInfoButton.setOnClickListener { - //查库 val result = DataBaseManager.get.queryMarkerById(markerId) if (result.isNotEmpty()) { navigatePageTo(markerId) } else { navigatePageTo(markerId) } - //查看完就把ID置空,便于下次查看最新的ID markerId = "" } } - 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() - try { - AlertMessageDialog.Builder().setContext(context) - .setTitle("温馨提示") - .setMessage("标识器埋深:${buffer.toBuryDepth()}厘米") - .setPositiveButton("知道了") - .setOnDialogButtonClickListener(object : - AlertMessageDialog.OnDialogButtonClickListener { - override fun onConfirmClick() { - updateSegment(CurrentSegment.SearchMarker) - } - }).build().show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } 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() + override fun onMarkerIdDetected(markerId: String) { + if (RuntimeCache.currentSegment == CurrentSegment.SearchMarker) { + binding.depthButton.isEnabled = true + binding.depthButton.setTextColor(Color.WHITE) + binding.depthButton.backgroundTintList = + ColorStateList.valueOf(Color.parseColor("#004364")) - //声音 - updateSound(signalEnergy) + binding.markerInfoButton.isEnabled = true + binding.markerInfoButton.setTextColor(Color.WHITE) + binding.markerInfoButton.backgroundTintList = + ColorStateList.valueOf(Color.parseColor("#FFA200")) - //信号强度显示 - updateProgressBar(signalEnergy) + handleMarker(markerId) + } + } - //搜索信号文字显示 - updateTextResult(signalEnergy) - } else { - Log.d(kTag, "乱码数据: ${buffer.contentToString()}") + private fun handleMarker(id: String) { + this.markerId = id + //自动上传标识器 + if (isExecuteTask) { + val taskId = SaveKeyValues.getValue(LocaleConstant.TASK_ID, "") as String + val taskCode = SaveKeyValues.getValue(LocaleConstant.TASK_CODE, "") as String + val taskMarkerLocalBean = DataBaseManager.get.queryTaskMarkerById( + taskId, taskCode, id, "0" + ) + taskMarkerLocalBean?.apply { + taskViewModel.uploadMarker(context, this) } } } - private fun updateSound(signalEnergy: Int) { - val soundResourceId = if (signalEnergy >= 4000) fastSoundResourceId else slowSoundResourceId - soundPool.play(soundResourceId, 1f, 1f, 0, 0, 1f) + override fun onMarkerDepthDetected(depth: Int) { + if (RuntimeCache.currentSegment == CurrentSegment.DetectDepth) { + detectDepthRunnable?.let { handler.removeCallbacks(it) } + detectDepthRunnable = null + LoadingDialog.dismiss() + AlertMessageDialog.Builder().setContext(context).setTitle("温馨提示") + .setMessage("标识器埋深:${depth}厘米").setPositiveButton("知道了") + .setOnDialogButtonClickListener(object : + AlertMessageDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + RuntimeCache.currentSegment = CurrentSegment.SearchMarker + sendSerialPortCommand(SerialPortCommand.SEARCH_SIGNAL) + } + }).build().show() + } } - private fun updateProgressBar(signalEnergy: Int) { - binding.energyPgBar.progress = signalEnergy - binding.energyValueView.text = "${signalEnergy}dB" + override fun onMarkerSignalDetected(signalEnergy: Int) { + if (RuntimeCache.currentSegment == CurrentSegment.SearchMarker) { + if (signalEnergy > 1000) { + binding.markerIdButton.isEnabled = true + binding.markerIdButton.setTextColor(Color.WHITE) + binding.markerIdButton.backgroundTintList = ColorStateList.valueOf( + Color.parseColor("#FFA200") + ) + + binding.searchResultView.text = "已检测到标识器" + binding.searchResultView.setTextColor(Color.parseColor("#428d00")) + binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_green) + } + + //声音 + val soundResourceId = if (signalEnergy >= 4000) + fastSoundResourceId else slowSoundResourceId + soundPool.play(soundResourceId, 1f, 1f, 0, 0, 1f) + + //信号强度显示 + binding.energyPgBar.progress = signalEnergy + binding.energyValueView.text = "${signalEnergy}dB" + + //搜索信号文字显示 + updateTextResult(signalEnergy) + } } private fun updateTextResult(signalEnergy: Int) { @@ -278,13 +262,19 @@ binding.energyTipsView.setBackgroundResource(backgroundRes) } + private val colorStateList = ColorStateList.valueOf(Color.parseColor("#8A8A8A")) + private val textColor = Color.parseColor("#CCCCCC") + private fun disableButtons() { binding.depthButton.isEnabled = false - binding.depthButton.setTextColor(Color.parseColor("#CCCCCC")) - binding.depthButton.setBackgroundResource(R.mipmap.left_button_disable) + binding.depthButton.setTextColor(textColor) + binding.depthButton.backgroundTintList = colorStateList + binding.markerIdButton.isEnabled = false + binding.markerIdButton.setTextColor(textColor) + binding.markerIdButton.backgroundTintList = colorStateList binding.markerInfoButton.isEnabled = false - binding.markerInfoButton.setTextColor(Color.parseColor("#CCCCCC")) - binding.markerInfoButton.setBackgroundResource(R.mipmap.right_button_disable) + binding.markerInfoButton.setTextColor(textColor) + binding.markerInfoButton.backgroundTintList = colorStateList } /** @@ -315,7 +305,8 @@ } } withContext(Dispatchers.Main) { - binding.radarScanView.renderPointData(dataPoints, + binding.radarScanView.renderPointData( + dataPoints, object : RadarScanView.OnGetNearestPointCallback { override fun getNearestPoint(point: RadarScanView.DataPoint?) { if (point == null) { @@ -331,8 +322,7 @@ binding.distancePgBar.progress = progress.toInt() } } - } - ) + }) } } } @@ -349,33 +339,6 @@ } - private fun handleMarker(id: String) { - this.markerId = id - - binding.depthButton.isEnabled = true - binding.depthButton.setTextColor(Color.WHITE) - binding.depthButton.setBackgroundResource(R.mipmap.left_button_enable) - binding.markerInfoButton.isEnabled = true - binding.markerInfoButton.setTextColor(Color.WHITE) - binding.markerInfoButton.setBackgroundResource(R.mipmap.right_button_enable) - - binding.searchResultView.text = "已检测到标识器" - binding.searchResultView.setTextColor(Color.parseColor("#428d00")) - binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_green) - - //自动上传标识器 - if (isExecuteTask) { - val taskId = SaveKeyValues.getValue(LocaleConstant.TASK_ID, "") as String - val taskCode = SaveKeyValues.getValue(LocaleConstant.TASK_CODE, "") as String - val taskMarkerLocalBean = DataBaseManager.get.queryTaskMarkerById( - taskId, taskCode, id, "0" - ) - taskMarkerLocalBean?.apply { - taskViewModel.uploadMarker(context, this) - } - } - } - override fun onResume() { super.onResume() //注册加速度传感器监听 @@ -421,7 +384,6 @@ override fun onDestroy() { super.onDestroy() - closeSerialPort() soundPool.autoPause() locationKit.stopLocation() } diff --git a/app/src/main/res/layout/activity_search_marker.xml b/app/src/main/res/layout/activity_search_marker.xml index 8e328c6..4fc9888 100644 --- a/app/src/main/res/layout/activity_search_marker.xml +++ b/app/src/main/res/layout/activity_search_marker.xml @@ -95,7 +95,7 @@ android:textColor="@color/white" /> - + - + android:orientation="horizontal">