diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 904657b..739ca8a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -62,7 +62,6 @@ - diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 904657b..739ca8a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -62,7 +62,6 @@ - diff --git "a/app/src/main/assets/SearchMarkerActivity - \346\274\224\347\244\272\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" "b/app/src/main/assets/SearchMarkerActivity - \346\274\224\347\244\272\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" deleted file mode 100644 index b3e68e3..0000000 --- "a/app/src/main/assets/SearchMarkerActivity - \346\274\224\347\244\272\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" +++ /dev/null @@ -1,447 +0,0 @@ -import android.content.res.ColorStateList -import android.graphics.Color -import android.hardware.Sensor -import android.hardware.SensorEvent -import android.hardware.SensorEventListener -import android.hardware.SensorManager -import android.media.AudioAttributes -import android.media.SoundPool -import android.os.Bundle -import android.os.Handler -import android.os.Looper -import android.view.View -import androidx.core.graphics.toColorInt -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.BaseApplication -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.model.MarkerDistanceData -import com.casic.common.detector.gd.utils.CurrentSegment -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.MarkerDetailDialog -import com.casic.common.detector.gd.widgets.NewMarkerDetailDialog -import com.casic.common.detector.gd.widgets.RadarScanView -import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.LiteKitConstant -import com.pengxh.kt.lite.utils.LoadingDialog -import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import kotlin.math.atan2 - -class SearchMarkerActivity : SerialPortBaseActivity(), - SensorEventListener { - - private val kTag = "SearchMarkerActivity" - private val context = this - private val locationKit by lazy { LocationKit(this) } - private val markerPoints by lazy { ArrayList() } - private val markerBeanDao by lazy { BaseApplication.get().dataBase.markerBeanDao() } - private val taskMarkerBeanDao by lazy { BaseApplication.get().dataBase.taskMarkerBeanDao() } - private val taskViewModel by lazy { ViewModelProvider(this)[TaskViewModel::class.java] } - private val sensorManager by lazy { getSystemService(SENSOR_SERVICE) as SensorManager } - private val attr = AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ALARM) - .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build() - private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build() - private val rotationMatrix = FloatArray(9)//旋转矩阵缓存 - private val valueArray = FloatArray(3)//方位角数值 - private var slowSoundResourceId = 0 - private var fastSoundResourceId = 0 - private var databaseMarkerId = ""//本地数据库标识器ID - private var detectedMarkerId = ""//真实探测到标识器ID - private var isExecuteTask = false - 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" - - slowSoundResourceId = soundPool.load(this, R.raw.ring4, 1) - fastSoundResourceId = soundPool.load(this, R.raw.ring2, 1) - - //点位渲染,每次定位都计算当前位置与符合条件的点距离 - locationKit.getCurrentLocation(false, object : OnGetLocationListener { - override fun onSuccess(location: AMapLocation) { - renderDataPoint(location) - } - - override fun onError() { - "当前位置信号差,无法获取定位".show(context) - } - }) - - if (isExecuteTask) { - binding.taskStateView.visibility = View.GONE - binding.taskStateView.isSelected = false - } else { - binding.taskStateView.visibility = View.VISIBLE - binding.taskStateView.isSelected = true - } - - //进入界面开始搜索信号强度 - sendSerialPortCommand(SerialPortCommand.SEARCH_SIGNAL) - } - - private val handler = Handler(Looper.getMainLooper()) - private var detectDepthRunnable: DetectDepthRunnable? = null - - private inner class DetectDepthRunnable(private val command: Int) : Runnable { - override fun run() { - sendSerialPortCommand(command) - //延迟三秒再发一次 - handler.postDelayed(this, 3000) - } - } - - override fun initEvent() { - binding.depthButton.setOnClickListener { - if (detectedMarkerId == "") { - //还没探测到,直接显示当初埋深 - val result = markerBeanDao.queryMarkerById(databaseMarkerId) - val depth = if (result.isNotEmpty()) { - "110厘米" - } else { - result.first().markerDepth - } - AlertMessageDialog.Builder() - .setContext(this) - .setTitle("温馨提示") - .setMessage("标识器埋深:$depth") - .setPositiveButton("知道了") - .setOnDialogButtonClickListener(object : - AlertMessageDialog.OnDialogButtonClickListener { - override fun onConfirmClick() { - RuntimeCache.currentSegment = CurrentSegment.SearchMarker - sendSerialPortCommand(SerialPortCommand.SEARCH_SIGNAL) - } - }).build().show() - return@setOnClickListener - } - - //真实探测埋深 - RuntimeCache.currentSegment = CurrentSegment.DetectDepth - val result = markerBeanDao.queryMarkerById(detectedMarkerId) - if (result.isNotEmpty()) { - 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 (command == SerialPortCommand.STOP_SERIAL_PORT_DATA) { - "此标识器无法读取埋深!".show(this) - } else { - soundPool.autoPause() - LoadingDialog.show(this, "正在探测标识器埋深,请稍后...") - - // 移除之前的 Runnable(如果存在) - detectDepthRunnable?.let { handler.removeCallbacks(it) } - detectDepthRunnable = DetectDepthRunnable(command) - // 发送读取标识器埋设深度指令 - handler.post(detectDepthRunnable!!) - } - } else { - "标识器未安装,安装成功后才可读取埋深!".show(this) - } - } - - binding.markerIdButton.setOnClickListener { - sendSerialPortCommand(SerialPortCommand.SEARCH_MARKER_ALWAYS) - } - - binding.markerInfoButton.setOnClickListener { - val markerId = if (detectedMarkerId == "") { - databaseMarkerId - } else { - detectedMarkerId - } - val result = markerBeanDao.queryMarkerById(markerId) - if (result.isNotEmpty()) { - MarkerDetailDialog(this).setMarker(result.first()).show() - } else { - NewMarkerDetailDialog(this, markerId) - } - //查询完之后重置ID,以便下次重走逻辑 - databaseMarkerId = "" - detectedMarkerId = "" - } - } - - override fun onMarkerIdDetected(markerId: String) { - if (RuntimeCache.currentSegment == CurrentSegment.SearchMarker) { - binding.depthButton.isEnabled = true - binding.depthButton.setTextColor(Color.WHITE) - binding.depthButton.backgroundTintList = - ColorStateList.valueOf("#004364".toColorInt()) - - binding.markerInfoButton.isEnabled = true - binding.markerInfoButton.setTextColor(Color.WHITE) - binding.markerInfoButton.backgroundTintList = - ColorStateList.valueOf("#FFA200".toColorInt()) - - handleMarker(markerId) - } - } - - private fun handleMarker(id: String) { - detectedMarkerId = id - //自动上传标识器 - if (isExecuteTask) { - val taskId = SaveKeyValues.getValue(LocaleConstant.TASK_ID, "") as String - val taskCode = SaveKeyValues.getValue(LocaleConstant.TASK_CODE, "") as String - val marker = taskMarkerBeanDao.queryTaskMarkerById( - taskId, taskCode, id, "0" - ) - if (marker == null) { - return - } - taskViewModel.uploadMarker( - marker.markerId, - onLoading = {}, - onSuccess = { - "标识器${marker.markerId}已探测!".show(this) - marker.isDetected = "1" - taskMarkerBeanDao.updateLocalTaskMarkerState(marker) - }, - onFailed = {} - ) - } - } - - override fun onMarkerDepthDetected(depth: Int) { - if (RuntimeCache.currentSegment == CurrentSegment.DetectDepth) { - detectDepthRunnable?.let { handler.removeCallbacks(it) } - detectDepthRunnable = null - LoadingDialog.dismiss() - if (!this.isDestroyed) { - 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() - } else { - "标识器埋深:${depth}厘米".show(this) - } - } - } - - override fun onMarkerSignalDetected(signalEnergy: Int) { - if (RuntimeCache.currentSegment == CurrentSegment.SearchMarker) { - if (signalEnergy > 1000) { - binding.markerIdButton.isEnabled = true - binding.markerIdButton.setTextColor("#428d00".toColorInt()) - binding.markerIdButton.backgroundTintList = ColorStateList.valueOf( - "#7EFF00".toColorInt() - ) - - binding.searchResultView.text = "已检测到标识器" - binding.searchResultView.setTextColor("#428d00".toColorInt()) - 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) { - when { - signalEnergy <= 700 -> { - setEnergyTip( - "信号较弱,可能距离较远", - "#8D1717".toColorInt(), - R.mipmap.bg_large_text_red - ) -// disableButtons() - binding.searchResultView.text = "未检测到标识器" - binding.searchResultView.setTextColor("#8D1717".toColorInt()) - binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_red) - } - - signalEnergy >= 4100 -> { - setEnergyTip( - "信号极强,接近标识器正上方", - "#428d00".toColorInt(), - R.mipmap.bg_large_text_green - ) - } - - else -> { - setEnergyTip( - "已靠近,请继续移动位置", - "#8C5700".toColorInt(), - R.mipmap.bg_large_text_yellow - ) - } - } - } - - private fun setEnergyTip(text: String, textColorRes: Int, backgroundRes: Int) { - binding.energyTipsView.text = text - binding.energyTipsView.setTextColor(textColorRes) - binding.energyTipsView.setBackgroundResource(backgroundRes) - } - - private val colorStateList = ColorStateList.valueOf("#8A8A8A".toColorInt()) - private val textColor = "#CCCCCC".toColorInt() - - private fun disableButtons() { - binding.depthButton.isEnabled = false - 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(textColor) - binding.markerInfoButton.backgroundTintList = colorStateList - } - - /** - * 计算并渲染数据点。点太多采用协程计算,不然会有点卡顿。默认2s计算一次 - * @param location 定位点(RTK获取) - * */ - private fun renderDataPoint(location: AMapLocation) { - val longitude = location.longitude - val latitude = location.latitude - lifecycleScope.launch(Dispatchers.IO) { - val dataPoints = ArrayList() - markerBeanDao.loadAll().forEach { - val distance = AMapUtils.calculateLineDistance( - LatLng(it.lat.toDouble(), it.lng.toDouble()), LatLng(latitude, longitude) - ) - val formatDistance = "%.2f".format(distance).toFloat() - markerPoints.add(MarkerDistanceData(it.markerId, formatDistance)) - - if (formatDistance <= LocaleConstant.MAX_DISTANCE) { - val angle = atan2( - (it.lat.toDouble() - latitude), (it.lng.toDouble() - longitude) - ) + Math.PI - val formatAngle = "%.2f".format(angle).toDouble() - - dataPoints.add( - RadarScanView.DataPoint(it.markerId, formatAngle, formatDistance) - ) - } - } - withContext(Dispatchers.Main) { - binding.radarScanView.renderPointData( - dataPoints, - onGetNearestPoint = { point -> - if (point == null) { - binding.distanceValueView.text = "大于5.5m" - binding.distancePgBar.progress = 100 - } else { - databaseMarkerId = point.markerId - - binding.depthButton.isEnabled = true - binding.depthButton.setTextColor(Color.WHITE) - binding.depthButton.backgroundTintList = - ColorStateList.valueOf("#004364".toColorInt()) - - binding.markerInfoButton.isEnabled = true - binding.markerInfoButton.setTextColor(Color.WHITE) - binding.markerInfoButton.backgroundTintList = - ColorStateList.valueOf("#FFA200".toColorInt()) - - binding.distanceValueView.text = "${point.distance}m" - val progress = if (point.distance > LocaleConstant.MAX_DISTANCE) { - 100 - } else { - (point.distance / LocaleConstant.MAX_DISTANCE) * 100 - } - binding.distancePgBar.progress = progress.toInt() - } - } - ) - } - } - } - - override fun initViewBinding(): ActivitySearchMarkerBinding { - return ActivitySearchMarkerBinding.inflate(layoutInflater) - } - - override fun setupTopBarLayout() { - - } - - override fun onResume() { - super.onResume() - //注册加速度传感器监听 - val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) - sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL) - - //注册磁场传感器监听 - val magnetic = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) - sensorManager.registerListener(this, magnetic, SensorManager.SENSOR_DELAY_NORMAL) - } - - override fun onPause() { - super.onPause() - sensorManager.unregisterListener(this) - } - - override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) { - //精度发生变化时触发 - } - - override fun onSensorChanged(event: SensorEvent?) { - //值发生变化时触发 - val type = event?.sensor?.type - - if (type == Sensor.TYPE_ACCELEROMETER) { - gravity = event.values - } else if (type == Sensor.TYPE_MAGNETIC_FIELD) { - geomagnetic = event.values - } - - if (gravity == null || geomagnetic == null) { - return - } - - if (SensorManager.getRotationMatrix(rotationMatrix, null, gravity, geomagnetic)) { - SensorManager.getOrientation(rotationMatrix, valueArray) - - val degree = ((360f + valueArray[0] * 180f / Math.PI) % 360).toInt() - //更新罗盘角度 - binding.radarScanView.setDegreeValue(degree) - } - } - - override fun onDestroy() { - super.onDestroy() - soundPool.autoPause() - locationKit.stopLocation() - } -} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 904657b..739ca8a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -62,7 +62,6 @@ - diff --git "a/app/src/main/assets/SearchMarkerActivity - \346\274\224\347\244\272\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" "b/app/src/main/assets/SearchMarkerActivity - \346\274\224\347\244\272\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" deleted file mode 100644 index b3e68e3..0000000 --- "a/app/src/main/assets/SearchMarkerActivity - \346\274\224\347\244\272\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" +++ /dev/null @@ -1,447 +0,0 @@ -import android.content.res.ColorStateList -import android.graphics.Color -import android.hardware.Sensor -import android.hardware.SensorEvent -import android.hardware.SensorEventListener -import android.hardware.SensorManager -import android.media.AudioAttributes -import android.media.SoundPool -import android.os.Bundle -import android.os.Handler -import android.os.Looper -import android.view.View -import androidx.core.graphics.toColorInt -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.BaseApplication -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.model.MarkerDistanceData -import com.casic.common.detector.gd.utils.CurrentSegment -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.MarkerDetailDialog -import com.casic.common.detector.gd.widgets.NewMarkerDetailDialog -import com.casic.common.detector.gd.widgets.RadarScanView -import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.LiteKitConstant -import com.pengxh.kt.lite.utils.LoadingDialog -import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import kotlin.math.atan2 - -class SearchMarkerActivity : SerialPortBaseActivity(), - SensorEventListener { - - private val kTag = "SearchMarkerActivity" - private val context = this - private val locationKit by lazy { LocationKit(this) } - private val markerPoints by lazy { ArrayList() } - private val markerBeanDao by lazy { BaseApplication.get().dataBase.markerBeanDao() } - private val taskMarkerBeanDao by lazy { BaseApplication.get().dataBase.taskMarkerBeanDao() } - private val taskViewModel by lazy { ViewModelProvider(this)[TaskViewModel::class.java] } - private val sensorManager by lazy { getSystemService(SENSOR_SERVICE) as SensorManager } - private val attr = AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ALARM) - .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build() - private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build() - private val rotationMatrix = FloatArray(9)//旋转矩阵缓存 - private val valueArray = FloatArray(3)//方位角数值 - private var slowSoundResourceId = 0 - private var fastSoundResourceId = 0 - private var databaseMarkerId = ""//本地数据库标识器ID - private var detectedMarkerId = ""//真实探测到标识器ID - private var isExecuteTask = false - 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" - - slowSoundResourceId = soundPool.load(this, R.raw.ring4, 1) - fastSoundResourceId = soundPool.load(this, R.raw.ring2, 1) - - //点位渲染,每次定位都计算当前位置与符合条件的点距离 - locationKit.getCurrentLocation(false, object : OnGetLocationListener { - override fun onSuccess(location: AMapLocation) { - renderDataPoint(location) - } - - override fun onError() { - "当前位置信号差,无法获取定位".show(context) - } - }) - - if (isExecuteTask) { - binding.taskStateView.visibility = View.GONE - binding.taskStateView.isSelected = false - } else { - binding.taskStateView.visibility = View.VISIBLE - binding.taskStateView.isSelected = true - } - - //进入界面开始搜索信号强度 - sendSerialPortCommand(SerialPortCommand.SEARCH_SIGNAL) - } - - private val handler = Handler(Looper.getMainLooper()) - private var detectDepthRunnable: DetectDepthRunnable? = null - - private inner class DetectDepthRunnable(private val command: Int) : Runnable { - override fun run() { - sendSerialPortCommand(command) - //延迟三秒再发一次 - handler.postDelayed(this, 3000) - } - } - - override fun initEvent() { - binding.depthButton.setOnClickListener { - if (detectedMarkerId == "") { - //还没探测到,直接显示当初埋深 - val result = markerBeanDao.queryMarkerById(databaseMarkerId) - val depth = if (result.isNotEmpty()) { - "110厘米" - } else { - result.first().markerDepth - } - AlertMessageDialog.Builder() - .setContext(this) - .setTitle("温馨提示") - .setMessage("标识器埋深:$depth") - .setPositiveButton("知道了") - .setOnDialogButtonClickListener(object : - AlertMessageDialog.OnDialogButtonClickListener { - override fun onConfirmClick() { - RuntimeCache.currentSegment = CurrentSegment.SearchMarker - sendSerialPortCommand(SerialPortCommand.SEARCH_SIGNAL) - } - }).build().show() - return@setOnClickListener - } - - //真实探测埋深 - RuntimeCache.currentSegment = CurrentSegment.DetectDepth - val result = markerBeanDao.queryMarkerById(detectedMarkerId) - if (result.isNotEmpty()) { - 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 (command == SerialPortCommand.STOP_SERIAL_PORT_DATA) { - "此标识器无法读取埋深!".show(this) - } else { - soundPool.autoPause() - LoadingDialog.show(this, "正在探测标识器埋深,请稍后...") - - // 移除之前的 Runnable(如果存在) - detectDepthRunnable?.let { handler.removeCallbacks(it) } - detectDepthRunnable = DetectDepthRunnable(command) - // 发送读取标识器埋设深度指令 - handler.post(detectDepthRunnable!!) - } - } else { - "标识器未安装,安装成功后才可读取埋深!".show(this) - } - } - - binding.markerIdButton.setOnClickListener { - sendSerialPortCommand(SerialPortCommand.SEARCH_MARKER_ALWAYS) - } - - binding.markerInfoButton.setOnClickListener { - val markerId = if (detectedMarkerId == "") { - databaseMarkerId - } else { - detectedMarkerId - } - val result = markerBeanDao.queryMarkerById(markerId) - if (result.isNotEmpty()) { - MarkerDetailDialog(this).setMarker(result.first()).show() - } else { - NewMarkerDetailDialog(this, markerId) - } - //查询完之后重置ID,以便下次重走逻辑 - databaseMarkerId = "" - detectedMarkerId = "" - } - } - - override fun onMarkerIdDetected(markerId: String) { - if (RuntimeCache.currentSegment == CurrentSegment.SearchMarker) { - binding.depthButton.isEnabled = true - binding.depthButton.setTextColor(Color.WHITE) - binding.depthButton.backgroundTintList = - ColorStateList.valueOf("#004364".toColorInt()) - - binding.markerInfoButton.isEnabled = true - binding.markerInfoButton.setTextColor(Color.WHITE) - binding.markerInfoButton.backgroundTintList = - ColorStateList.valueOf("#FFA200".toColorInt()) - - handleMarker(markerId) - } - } - - private fun handleMarker(id: String) { - detectedMarkerId = id - //自动上传标识器 - if (isExecuteTask) { - val taskId = SaveKeyValues.getValue(LocaleConstant.TASK_ID, "") as String - val taskCode = SaveKeyValues.getValue(LocaleConstant.TASK_CODE, "") as String - val marker = taskMarkerBeanDao.queryTaskMarkerById( - taskId, taskCode, id, "0" - ) - if (marker == null) { - return - } - taskViewModel.uploadMarker( - marker.markerId, - onLoading = {}, - onSuccess = { - "标识器${marker.markerId}已探测!".show(this) - marker.isDetected = "1" - taskMarkerBeanDao.updateLocalTaskMarkerState(marker) - }, - onFailed = {} - ) - } - } - - override fun onMarkerDepthDetected(depth: Int) { - if (RuntimeCache.currentSegment == CurrentSegment.DetectDepth) { - detectDepthRunnable?.let { handler.removeCallbacks(it) } - detectDepthRunnable = null - LoadingDialog.dismiss() - if (!this.isDestroyed) { - 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() - } else { - "标识器埋深:${depth}厘米".show(this) - } - } - } - - override fun onMarkerSignalDetected(signalEnergy: Int) { - if (RuntimeCache.currentSegment == CurrentSegment.SearchMarker) { - if (signalEnergy > 1000) { - binding.markerIdButton.isEnabled = true - binding.markerIdButton.setTextColor("#428d00".toColorInt()) - binding.markerIdButton.backgroundTintList = ColorStateList.valueOf( - "#7EFF00".toColorInt() - ) - - binding.searchResultView.text = "已检测到标识器" - binding.searchResultView.setTextColor("#428d00".toColorInt()) - 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) { - when { - signalEnergy <= 700 -> { - setEnergyTip( - "信号较弱,可能距离较远", - "#8D1717".toColorInt(), - R.mipmap.bg_large_text_red - ) -// disableButtons() - binding.searchResultView.text = "未检测到标识器" - binding.searchResultView.setTextColor("#8D1717".toColorInt()) - binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_red) - } - - signalEnergy >= 4100 -> { - setEnergyTip( - "信号极强,接近标识器正上方", - "#428d00".toColorInt(), - R.mipmap.bg_large_text_green - ) - } - - else -> { - setEnergyTip( - "已靠近,请继续移动位置", - "#8C5700".toColorInt(), - R.mipmap.bg_large_text_yellow - ) - } - } - } - - private fun setEnergyTip(text: String, textColorRes: Int, backgroundRes: Int) { - binding.energyTipsView.text = text - binding.energyTipsView.setTextColor(textColorRes) - binding.energyTipsView.setBackgroundResource(backgroundRes) - } - - private val colorStateList = ColorStateList.valueOf("#8A8A8A".toColorInt()) - private val textColor = "#CCCCCC".toColorInt() - - private fun disableButtons() { - binding.depthButton.isEnabled = false - 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(textColor) - binding.markerInfoButton.backgroundTintList = colorStateList - } - - /** - * 计算并渲染数据点。点太多采用协程计算,不然会有点卡顿。默认2s计算一次 - * @param location 定位点(RTK获取) - * */ - private fun renderDataPoint(location: AMapLocation) { - val longitude = location.longitude - val latitude = location.latitude - lifecycleScope.launch(Dispatchers.IO) { - val dataPoints = ArrayList() - markerBeanDao.loadAll().forEach { - val distance = AMapUtils.calculateLineDistance( - LatLng(it.lat.toDouble(), it.lng.toDouble()), LatLng(latitude, longitude) - ) - val formatDistance = "%.2f".format(distance).toFloat() - markerPoints.add(MarkerDistanceData(it.markerId, formatDistance)) - - if (formatDistance <= LocaleConstant.MAX_DISTANCE) { - val angle = atan2( - (it.lat.toDouble() - latitude), (it.lng.toDouble() - longitude) - ) + Math.PI - val formatAngle = "%.2f".format(angle).toDouble() - - dataPoints.add( - RadarScanView.DataPoint(it.markerId, formatAngle, formatDistance) - ) - } - } - withContext(Dispatchers.Main) { - binding.radarScanView.renderPointData( - dataPoints, - onGetNearestPoint = { point -> - if (point == null) { - binding.distanceValueView.text = "大于5.5m" - binding.distancePgBar.progress = 100 - } else { - databaseMarkerId = point.markerId - - binding.depthButton.isEnabled = true - binding.depthButton.setTextColor(Color.WHITE) - binding.depthButton.backgroundTintList = - ColorStateList.valueOf("#004364".toColorInt()) - - binding.markerInfoButton.isEnabled = true - binding.markerInfoButton.setTextColor(Color.WHITE) - binding.markerInfoButton.backgroundTintList = - ColorStateList.valueOf("#FFA200".toColorInt()) - - binding.distanceValueView.text = "${point.distance}m" - val progress = if (point.distance > LocaleConstant.MAX_DISTANCE) { - 100 - } else { - (point.distance / LocaleConstant.MAX_DISTANCE) * 100 - } - binding.distancePgBar.progress = progress.toInt() - } - } - ) - } - } - } - - override fun initViewBinding(): ActivitySearchMarkerBinding { - return ActivitySearchMarkerBinding.inflate(layoutInflater) - } - - override fun setupTopBarLayout() { - - } - - override fun onResume() { - super.onResume() - //注册加速度传感器监听 - val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) - sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL) - - //注册磁场传感器监听 - val magnetic = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) - sensorManager.registerListener(this, magnetic, SensorManager.SENSOR_DELAY_NORMAL) - } - - override fun onPause() { - super.onPause() - sensorManager.unregisterListener(this) - } - - override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) { - //精度发生变化时触发 - } - - override fun onSensorChanged(event: SensorEvent?) { - //值发生变化时触发 - val type = event?.sensor?.type - - if (type == Sensor.TYPE_ACCELEROMETER) { - gravity = event.values - } else if (type == Sensor.TYPE_MAGNETIC_FIELD) { - geomagnetic = event.values - } - - if (gravity == null || geomagnetic == null) { - return - } - - if (SensorManager.getRotationMatrix(rotationMatrix, null, gravity, geomagnetic)) { - SensorManager.getOrientation(rotationMatrix, valueArray) - - val degree = ((360f + valueArray[0] * 180f / Math.PI) % 360).toInt() - //更新罗盘角度 - binding.radarScanView.setDegreeValue(degree) - } - } - - override fun onDestroy() { - super.onDestroy() - soundPool.autoPause() - locationKit.stopLocation() - } -} \ No newline at end of file diff --git "a/app/src/main/assets/\345\256\241\350\256\241\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" "b/app/src/main/assets/\345\256\241\350\256\241\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" new file mode 100644 index 0000000..c4af67a --- /dev/null +++ "b/app/src/main/assets/\345\256\241\350\256\241\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" @@ -0,0 +1,189 @@ +import android.hardware.Sensor +import android.hardware.SensorEvent +import android.hardware.SensorEventListener +import android.hardware.SensorManager +import android.media.AudioAttributes +import android.media.SoundPool +import android.os.Bundle +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.BaseApplication +import com.casic.common.detector.gd.callback.OnGetLocationListener +import com.casic.common.detector.gd.databinding.ActivitySearchMarkerAuditBinding +import com.casic.common.detector.gd.utils.LocaleConstant +import com.casic.common.detector.gd.utils.LocationKit +import com.casic.common.detector.gd.widgets.MarkerDetailDialog +import com.casic.common.detector.gd.widgets.NewMarkerDetailDialog +import com.casic.common.detector.gd.widgets.RadarScanView +import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.extensions.show +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 : KotlinBaseActivity(), + SensorEventListener { + + private val kTag = "SearchMarkerActivity" + private val context = this + private val locationKit by lazy { LocationKit(this) } + private val sensorManager by lazy { getSystemService(SENSOR_SERVICE) as SensorManager } + private val markerBeanDao by lazy { BaseApplication.Companion.get().dataBase.markerBeanDao() } + private val attr = AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ALARM) + .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build() + private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build() + private val rotationMatrix = FloatArray(9)//旋转矩阵缓存 + private val valueArray = FloatArray(3)//方位角数值 + private var nearestMarkerId = ""//探测不到标识器的时候计算出来的最近的标识器ID + private var gravity: FloatArray? = null + private var geomagnetic: FloatArray? = null + private lateinit var searchSignalEnergyTimer: Timer + + override fun initOnCreate(savedInstanceState: Bundle?) { + val fastSoundResourceId = soundPool.load(this, R.raw.ring2, 1) + + //点位渲染,每次定位都计算当前位置与符合条件的点距离 + locationKit.getCurrentLocation(false, object : OnGetLocationListener { + override fun onSuccess(location: AMapLocation) { + renderDataPoint(location) + } + + override fun onError() { + "当前位置信号差,无法获取定位".show(context) + } + }) + + searchSignalEnergyTimer = Timer() + searchSignalEnergyTimer.schedule(object : TimerTask() { + override fun run() { + soundPool.play(fastSoundResourceId, 1f, 1f, 0, 0, 1f) + } + }, 0, 100) + } + + override fun initEvent() { + binding.markerInfoButton.setOnClickListener { + //查库 + val result = markerBeanDao.queryMarkerById(nearestMarkerId) + if (result.isNotEmpty()) { + MarkerDetailDialog(this).setMarker(result.first()).show() + } else { + NewMarkerDetailDialog(this, nearestMarkerId) + } + } + } + + /** + * 计算并渲染数据点。点太多采用协程计算,不然会有点卡顿。默认2s计算一次 + * @param location 定位点(RTK获取) + * */ + private fun renderDataPoint(location: AMapLocation) { + val longitude = location.longitude + val latitude = location.latitude + lifecycleScope.launch(Dispatchers.IO) { + val dataPoints = ArrayList() + markerBeanDao.loadAll().forEach { + val distance = AMapUtils.calculateLineDistance( + LatLng(it.lat.toDouble(), it.lng.toDouble()), LatLng(latitude, longitude) + ) + val formatDistance = "%.2f".format(distance).toFloat() + val angle = atan2( + (it.lat.toDouble() - latitude), (it.lng.toDouble() - longitude) + ) + Math.PI + val formatAngle = "%.2f".format(angle).toDouble() + + dataPoints.add( + RadarScanView.DataPoint(it.markerId, formatAngle, formatDistance) + ) + } + withContext(Dispatchers.Main) { + binding.radarScanView.renderPointData( + dataPoints, + onGetNearestPoint = { point -> + if (point == null) { + binding.distanceValueView.text = "大于5.5m" + binding.distancePgBar.progress = 100 + } else { + nearestMarkerId = point.markerId + binding.distanceValueView.text = "${point.distance}m" + val progress = if (point.distance > LocaleConstant.MAX_DISTANCE) { + 100 + } else { + (point.distance / LocaleConstant.MAX_DISTANCE) * 100 + } + binding.distancePgBar.progress = progress.toInt() + } + } + ) + } + } + } + + override fun initViewBinding(): ActivitySearchMarkerAuditBinding { + return ActivitySearchMarkerAuditBinding.inflate(layoutInflater) + } + + override fun observeRequestState() { + + } + + override fun setupTopBarLayout() { + + } + + override fun onResume() { + super.onResume() + //注册加速度传感器监听 + val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) + sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL) + + //注册磁场传感器监听 + val magnetic = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) + sensorManager.registerListener(this, magnetic, SensorManager.SENSOR_DELAY_NORMAL) + } + + override fun onPause() { + super.onPause() + sensorManager.unregisterListener(this) + } + + override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) { + //精度发生变化时触发 + } + + override fun onSensorChanged(event: SensorEvent?) { + //值发生变化时触发 + val type = event?.sensor?.type + + if (type == Sensor.TYPE_ACCELEROMETER) { + gravity = event.values + } else if (type == Sensor.TYPE_MAGNETIC_FIELD) { + geomagnetic = event.values + } + + if (gravity == null || geomagnetic == null) { + return + } + + if (SensorManager.getRotationMatrix(rotationMatrix, null, gravity, geomagnetic)) { + SensorManager.getOrientation(rotationMatrix, valueArray) + + val degree = ((360f + valueArray[0] * 180f / Math.PI) % 360).toInt() + //更新罗盘角度 + binding.radarScanView.setDegreeValue(degree) + } + } + + override fun onDestroy() { + super.onDestroy() + searchSignalEnergyTimer.cancel() + soundPool.release() + locationKit.stopLocation() + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 904657b..739ca8a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -62,7 +62,6 @@ - diff --git "a/app/src/main/assets/SearchMarkerActivity - \346\274\224\347\244\272\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" "b/app/src/main/assets/SearchMarkerActivity - \346\274\224\347\244\272\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" deleted file mode 100644 index b3e68e3..0000000 --- "a/app/src/main/assets/SearchMarkerActivity - \346\274\224\347\244\272\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" +++ /dev/null @@ -1,447 +0,0 @@ -import android.content.res.ColorStateList -import android.graphics.Color -import android.hardware.Sensor -import android.hardware.SensorEvent -import android.hardware.SensorEventListener -import android.hardware.SensorManager -import android.media.AudioAttributes -import android.media.SoundPool -import android.os.Bundle -import android.os.Handler -import android.os.Looper -import android.view.View -import androidx.core.graphics.toColorInt -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.BaseApplication -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.model.MarkerDistanceData -import com.casic.common.detector.gd.utils.CurrentSegment -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.MarkerDetailDialog -import com.casic.common.detector.gd.widgets.NewMarkerDetailDialog -import com.casic.common.detector.gd.widgets.RadarScanView -import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.LiteKitConstant -import com.pengxh.kt.lite.utils.LoadingDialog -import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import kotlin.math.atan2 - -class SearchMarkerActivity : SerialPortBaseActivity(), - SensorEventListener { - - private val kTag = "SearchMarkerActivity" - private val context = this - private val locationKit by lazy { LocationKit(this) } - private val markerPoints by lazy { ArrayList() } - private val markerBeanDao by lazy { BaseApplication.get().dataBase.markerBeanDao() } - private val taskMarkerBeanDao by lazy { BaseApplication.get().dataBase.taskMarkerBeanDao() } - private val taskViewModel by lazy { ViewModelProvider(this)[TaskViewModel::class.java] } - private val sensorManager by lazy { getSystemService(SENSOR_SERVICE) as SensorManager } - private val attr = AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ALARM) - .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build() - private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build() - private val rotationMatrix = FloatArray(9)//旋转矩阵缓存 - private val valueArray = FloatArray(3)//方位角数值 - private var slowSoundResourceId = 0 - private var fastSoundResourceId = 0 - private var databaseMarkerId = ""//本地数据库标识器ID - private var detectedMarkerId = ""//真实探测到标识器ID - private var isExecuteTask = false - 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" - - slowSoundResourceId = soundPool.load(this, R.raw.ring4, 1) - fastSoundResourceId = soundPool.load(this, R.raw.ring2, 1) - - //点位渲染,每次定位都计算当前位置与符合条件的点距离 - locationKit.getCurrentLocation(false, object : OnGetLocationListener { - override fun onSuccess(location: AMapLocation) { - renderDataPoint(location) - } - - override fun onError() { - "当前位置信号差,无法获取定位".show(context) - } - }) - - if (isExecuteTask) { - binding.taskStateView.visibility = View.GONE - binding.taskStateView.isSelected = false - } else { - binding.taskStateView.visibility = View.VISIBLE - binding.taskStateView.isSelected = true - } - - //进入界面开始搜索信号强度 - sendSerialPortCommand(SerialPortCommand.SEARCH_SIGNAL) - } - - private val handler = Handler(Looper.getMainLooper()) - private var detectDepthRunnable: DetectDepthRunnable? = null - - private inner class DetectDepthRunnable(private val command: Int) : Runnable { - override fun run() { - sendSerialPortCommand(command) - //延迟三秒再发一次 - handler.postDelayed(this, 3000) - } - } - - override fun initEvent() { - binding.depthButton.setOnClickListener { - if (detectedMarkerId == "") { - //还没探测到,直接显示当初埋深 - val result = markerBeanDao.queryMarkerById(databaseMarkerId) - val depth = if (result.isNotEmpty()) { - "110厘米" - } else { - result.first().markerDepth - } - AlertMessageDialog.Builder() - .setContext(this) - .setTitle("温馨提示") - .setMessage("标识器埋深:$depth") - .setPositiveButton("知道了") - .setOnDialogButtonClickListener(object : - AlertMessageDialog.OnDialogButtonClickListener { - override fun onConfirmClick() { - RuntimeCache.currentSegment = CurrentSegment.SearchMarker - sendSerialPortCommand(SerialPortCommand.SEARCH_SIGNAL) - } - }).build().show() - return@setOnClickListener - } - - //真实探测埋深 - RuntimeCache.currentSegment = CurrentSegment.DetectDepth - val result = markerBeanDao.queryMarkerById(detectedMarkerId) - if (result.isNotEmpty()) { - 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 (command == SerialPortCommand.STOP_SERIAL_PORT_DATA) { - "此标识器无法读取埋深!".show(this) - } else { - soundPool.autoPause() - LoadingDialog.show(this, "正在探测标识器埋深,请稍后...") - - // 移除之前的 Runnable(如果存在) - detectDepthRunnable?.let { handler.removeCallbacks(it) } - detectDepthRunnable = DetectDepthRunnable(command) - // 发送读取标识器埋设深度指令 - handler.post(detectDepthRunnable!!) - } - } else { - "标识器未安装,安装成功后才可读取埋深!".show(this) - } - } - - binding.markerIdButton.setOnClickListener { - sendSerialPortCommand(SerialPortCommand.SEARCH_MARKER_ALWAYS) - } - - binding.markerInfoButton.setOnClickListener { - val markerId = if (detectedMarkerId == "") { - databaseMarkerId - } else { - detectedMarkerId - } - val result = markerBeanDao.queryMarkerById(markerId) - if (result.isNotEmpty()) { - MarkerDetailDialog(this).setMarker(result.first()).show() - } else { - NewMarkerDetailDialog(this, markerId) - } - //查询完之后重置ID,以便下次重走逻辑 - databaseMarkerId = "" - detectedMarkerId = "" - } - } - - override fun onMarkerIdDetected(markerId: String) { - if (RuntimeCache.currentSegment == CurrentSegment.SearchMarker) { - binding.depthButton.isEnabled = true - binding.depthButton.setTextColor(Color.WHITE) - binding.depthButton.backgroundTintList = - ColorStateList.valueOf("#004364".toColorInt()) - - binding.markerInfoButton.isEnabled = true - binding.markerInfoButton.setTextColor(Color.WHITE) - binding.markerInfoButton.backgroundTintList = - ColorStateList.valueOf("#FFA200".toColorInt()) - - handleMarker(markerId) - } - } - - private fun handleMarker(id: String) { - detectedMarkerId = id - //自动上传标识器 - if (isExecuteTask) { - val taskId = SaveKeyValues.getValue(LocaleConstant.TASK_ID, "") as String - val taskCode = SaveKeyValues.getValue(LocaleConstant.TASK_CODE, "") as String - val marker = taskMarkerBeanDao.queryTaskMarkerById( - taskId, taskCode, id, "0" - ) - if (marker == null) { - return - } - taskViewModel.uploadMarker( - marker.markerId, - onLoading = {}, - onSuccess = { - "标识器${marker.markerId}已探测!".show(this) - marker.isDetected = "1" - taskMarkerBeanDao.updateLocalTaskMarkerState(marker) - }, - onFailed = {} - ) - } - } - - override fun onMarkerDepthDetected(depth: Int) { - if (RuntimeCache.currentSegment == CurrentSegment.DetectDepth) { - detectDepthRunnable?.let { handler.removeCallbacks(it) } - detectDepthRunnable = null - LoadingDialog.dismiss() - if (!this.isDestroyed) { - 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() - } else { - "标识器埋深:${depth}厘米".show(this) - } - } - } - - override fun onMarkerSignalDetected(signalEnergy: Int) { - if (RuntimeCache.currentSegment == CurrentSegment.SearchMarker) { - if (signalEnergy > 1000) { - binding.markerIdButton.isEnabled = true - binding.markerIdButton.setTextColor("#428d00".toColorInt()) - binding.markerIdButton.backgroundTintList = ColorStateList.valueOf( - "#7EFF00".toColorInt() - ) - - binding.searchResultView.text = "已检测到标识器" - binding.searchResultView.setTextColor("#428d00".toColorInt()) - 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) { - when { - signalEnergy <= 700 -> { - setEnergyTip( - "信号较弱,可能距离较远", - "#8D1717".toColorInt(), - R.mipmap.bg_large_text_red - ) -// disableButtons() - binding.searchResultView.text = "未检测到标识器" - binding.searchResultView.setTextColor("#8D1717".toColorInt()) - binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_red) - } - - signalEnergy >= 4100 -> { - setEnergyTip( - "信号极强,接近标识器正上方", - "#428d00".toColorInt(), - R.mipmap.bg_large_text_green - ) - } - - else -> { - setEnergyTip( - "已靠近,请继续移动位置", - "#8C5700".toColorInt(), - R.mipmap.bg_large_text_yellow - ) - } - } - } - - private fun setEnergyTip(text: String, textColorRes: Int, backgroundRes: Int) { - binding.energyTipsView.text = text - binding.energyTipsView.setTextColor(textColorRes) - binding.energyTipsView.setBackgroundResource(backgroundRes) - } - - private val colorStateList = ColorStateList.valueOf("#8A8A8A".toColorInt()) - private val textColor = "#CCCCCC".toColorInt() - - private fun disableButtons() { - binding.depthButton.isEnabled = false - 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(textColor) - binding.markerInfoButton.backgroundTintList = colorStateList - } - - /** - * 计算并渲染数据点。点太多采用协程计算,不然会有点卡顿。默认2s计算一次 - * @param location 定位点(RTK获取) - * */ - private fun renderDataPoint(location: AMapLocation) { - val longitude = location.longitude - val latitude = location.latitude - lifecycleScope.launch(Dispatchers.IO) { - val dataPoints = ArrayList() - markerBeanDao.loadAll().forEach { - val distance = AMapUtils.calculateLineDistance( - LatLng(it.lat.toDouble(), it.lng.toDouble()), LatLng(latitude, longitude) - ) - val formatDistance = "%.2f".format(distance).toFloat() - markerPoints.add(MarkerDistanceData(it.markerId, formatDistance)) - - if (formatDistance <= LocaleConstant.MAX_DISTANCE) { - val angle = atan2( - (it.lat.toDouble() - latitude), (it.lng.toDouble() - longitude) - ) + Math.PI - val formatAngle = "%.2f".format(angle).toDouble() - - dataPoints.add( - RadarScanView.DataPoint(it.markerId, formatAngle, formatDistance) - ) - } - } - withContext(Dispatchers.Main) { - binding.radarScanView.renderPointData( - dataPoints, - onGetNearestPoint = { point -> - if (point == null) { - binding.distanceValueView.text = "大于5.5m" - binding.distancePgBar.progress = 100 - } else { - databaseMarkerId = point.markerId - - binding.depthButton.isEnabled = true - binding.depthButton.setTextColor(Color.WHITE) - binding.depthButton.backgroundTintList = - ColorStateList.valueOf("#004364".toColorInt()) - - binding.markerInfoButton.isEnabled = true - binding.markerInfoButton.setTextColor(Color.WHITE) - binding.markerInfoButton.backgroundTintList = - ColorStateList.valueOf("#FFA200".toColorInt()) - - binding.distanceValueView.text = "${point.distance}m" - val progress = if (point.distance > LocaleConstant.MAX_DISTANCE) { - 100 - } else { - (point.distance / LocaleConstant.MAX_DISTANCE) * 100 - } - binding.distancePgBar.progress = progress.toInt() - } - } - ) - } - } - } - - override fun initViewBinding(): ActivitySearchMarkerBinding { - return ActivitySearchMarkerBinding.inflate(layoutInflater) - } - - override fun setupTopBarLayout() { - - } - - override fun onResume() { - super.onResume() - //注册加速度传感器监听 - val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) - sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL) - - //注册磁场传感器监听 - val magnetic = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) - sensorManager.registerListener(this, magnetic, SensorManager.SENSOR_DELAY_NORMAL) - } - - override fun onPause() { - super.onPause() - sensorManager.unregisterListener(this) - } - - override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) { - //精度发生变化时触发 - } - - override fun onSensorChanged(event: SensorEvent?) { - //值发生变化时触发 - val type = event?.sensor?.type - - if (type == Sensor.TYPE_ACCELEROMETER) { - gravity = event.values - } else if (type == Sensor.TYPE_MAGNETIC_FIELD) { - geomagnetic = event.values - } - - if (gravity == null || geomagnetic == null) { - return - } - - if (SensorManager.getRotationMatrix(rotationMatrix, null, gravity, geomagnetic)) { - SensorManager.getOrientation(rotationMatrix, valueArray) - - val degree = ((360f + valueArray[0] * 180f / Math.PI) % 360).toInt() - //更新罗盘角度 - binding.radarScanView.setDegreeValue(degree) - } - } - - override fun onDestroy() { - super.onDestroy() - soundPool.autoPause() - locationKit.stopLocation() - } -} \ No newline at end of file diff --git "a/app/src/main/assets/\345\256\241\350\256\241\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" "b/app/src/main/assets/\345\256\241\350\256\241\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" new file mode 100644 index 0000000..c4af67a --- /dev/null +++ "b/app/src/main/assets/\345\256\241\350\256\241\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" @@ -0,0 +1,189 @@ +import android.hardware.Sensor +import android.hardware.SensorEvent +import android.hardware.SensorEventListener +import android.hardware.SensorManager +import android.media.AudioAttributes +import android.media.SoundPool +import android.os.Bundle +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.BaseApplication +import com.casic.common.detector.gd.callback.OnGetLocationListener +import com.casic.common.detector.gd.databinding.ActivitySearchMarkerAuditBinding +import com.casic.common.detector.gd.utils.LocaleConstant +import com.casic.common.detector.gd.utils.LocationKit +import com.casic.common.detector.gd.widgets.MarkerDetailDialog +import com.casic.common.detector.gd.widgets.NewMarkerDetailDialog +import com.casic.common.detector.gd.widgets.RadarScanView +import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.extensions.show +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 : KotlinBaseActivity(), + SensorEventListener { + + private val kTag = "SearchMarkerActivity" + private val context = this + private val locationKit by lazy { LocationKit(this) } + private val sensorManager by lazy { getSystemService(SENSOR_SERVICE) as SensorManager } + private val markerBeanDao by lazy { BaseApplication.Companion.get().dataBase.markerBeanDao() } + private val attr = AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ALARM) + .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build() + private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build() + private val rotationMatrix = FloatArray(9)//旋转矩阵缓存 + private val valueArray = FloatArray(3)//方位角数值 + private var nearestMarkerId = ""//探测不到标识器的时候计算出来的最近的标识器ID + private var gravity: FloatArray? = null + private var geomagnetic: FloatArray? = null + private lateinit var searchSignalEnergyTimer: Timer + + override fun initOnCreate(savedInstanceState: Bundle?) { + val fastSoundResourceId = soundPool.load(this, R.raw.ring2, 1) + + //点位渲染,每次定位都计算当前位置与符合条件的点距离 + locationKit.getCurrentLocation(false, object : OnGetLocationListener { + override fun onSuccess(location: AMapLocation) { + renderDataPoint(location) + } + + override fun onError() { + "当前位置信号差,无法获取定位".show(context) + } + }) + + searchSignalEnergyTimer = Timer() + searchSignalEnergyTimer.schedule(object : TimerTask() { + override fun run() { + soundPool.play(fastSoundResourceId, 1f, 1f, 0, 0, 1f) + } + }, 0, 100) + } + + override fun initEvent() { + binding.markerInfoButton.setOnClickListener { + //查库 + val result = markerBeanDao.queryMarkerById(nearestMarkerId) + if (result.isNotEmpty()) { + MarkerDetailDialog(this).setMarker(result.first()).show() + } else { + NewMarkerDetailDialog(this, nearestMarkerId) + } + } + } + + /** + * 计算并渲染数据点。点太多采用协程计算,不然会有点卡顿。默认2s计算一次 + * @param location 定位点(RTK获取) + * */ + private fun renderDataPoint(location: AMapLocation) { + val longitude = location.longitude + val latitude = location.latitude + lifecycleScope.launch(Dispatchers.IO) { + val dataPoints = ArrayList() + markerBeanDao.loadAll().forEach { + val distance = AMapUtils.calculateLineDistance( + LatLng(it.lat.toDouble(), it.lng.toDouble()), LatLng(latitude, longitude) + ) + val formatDistance = "%.2f".format(distance).toFloat() + val angle = atan2( + (it.lat.toDouble() - latitude), (it.lng.toDouble() - longitude) + ) + Math.PI + val formatAngle = "%.2f".format(angle).toDouble() + + dataPoints.add( + RadarScanView.DataPoint(it.markerId, formatAngle, formatDistance) + ) + } + withContext(Dispatchers.Main) { + binding.radarScanView.renderPointData( + dataPoints, + onGetNearestPoint = { point -> + if (point == null) { + binding.distanceValueView.text = "大于5.5m" + binding.distancePgBar.progress = 100 + } else { + nearestMarkerId = point.markerId + binding.distanceValueView.text = "${point.distance}m" + val progress = if (point.distance > LocaleConstant.MAX_DISTANCE) { + 100 + } else { + (point.distance / LocaleConstant.MAX_DISTANCE) * 100 + } + binding.distancePgBar.progress = progress.toInt() + } + } + ) + } + } + } + + override fun initViewBinding(): ActivitySearchMarkerAuditBinding { + return ActivitySearchMarkerAuditBinding.inflate(layoutInflater) + } + + override fun observeRequestState() { + + } + + override fun setupTopBarLayout() { + + } + + override fun onResume() { + super.onResume() + //注册加速度传感器监听 + val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) + sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL) + + //注册磁场传感器监听 + val magnetic = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) + sensorManager.registerListener(this, magnetic, SensorManager.SENSOR_DELAY_NORMAL) + } + + override fun onPause() { + super.onPause() + sensorManager.unregisterListener(this) + } + + override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) { + //精度发生变化时触发 + } + + override fun onSensorChanged(event: SensorEvent?) { + //值发生变化时触发 + val type = event?.sensor?.type + + if (type == Sensor.TYPE_ACCELEROMETER) { + gravity = event.values + } else if (type == Sensor.TYPE_MAGNETIC_FIELD) { + geomagnetic = event.values + } + + if (gravity == null || geomagnetic == null) { + return + } + + if (SensorManager.getRotationMatrix(rotationMatrix, null, gravity, geomagnetic)) { + SensorManager.getOrientation(rotationMatrix, valueArray) + + val degree = ((360f + valueArray[0] * 180f / Math.PI) % 360).toInt() + //更新罗盘角度 + binding.radarScanView.setDegreeValue(degree) + } + } + + override fun onDestroy() { + super.onDestroy() + searchSignalEnergyTimer.cancel() + soundPool.release() + locationKit.stopLocation() + } +} \ No newline at end of file diff --git "a/app/src/main/assets/\346\274\224\347\244\272\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" "b/app/src/main/assets/\346\274\224\347\244\272\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" new file mode 100644 index 0000000..597b2cd --- /dev/null +++ "b/app/src/main/assets/\346\274\224\347\244\272\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" @@ -0,0 +1,431 @@ +import android.content.res.ColorStateList +import android.graphics.Color +import android.hardware.Sensor +import android.hardware.SensorEvent +import android.hardware.SensorEventListener +import android.hardware.SensorManager +import android.media.AudioAttributes +import android.media.SoundPool +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.view.View +import androidx.core.graphics.toColorInt +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.BaseApplication +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.model.MarkerDistanceData +import com.casic.common.detector.gd.utils.CurrentSegment +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.MarkerDetailDialog +import com.casic.common.detector.gd.widgets.NewMarkerDetailDialog +import com.casic.common.detector.gd.widgets.RadarScanView +import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadingDialog +import com.pengxh.kt.lite.utils.SaveKeyValues +import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import kotlin.math.atan2 + +class SearchMarkerActivity : SerialPortBaseActivity(), + SensorEventListener { + + private val kTag = "SearchMarkerActivity" + private val context = this + private val locationKit by lazy { LocationKit(this) } + private val markerPoints by lazy { ArrayList() } + private val markerBeanDao by lazy { BaseApplication.get().dataBase.markerBeanDao() } + private val taskMarkerBeanDao by lazy { BaseApplication.get().dataBase.taskMarkerBeanDao() } + private val taskViewModel by lazy { ViewModelProvider(this)[TaskViewModel::class.java] } + private val sensorManager by lazy { getSystemService(SENSOR_SERVICE) as SensorManager } + private val attr = AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ALARM) + .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build() + private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build() + private val rotationMatrix = FloatArray(9)//旋转矩阵缓存 + private val valueArray = FloatArray(3)//方位角数值 + private var slowSoundResourceId = 0 + private var fastSoundResourceId = 0 + private var databaseMarkerId = ""//本地数据库标识器ID + private var detectedMarkerId = ""//真实探测到标识器ID + private var isExecuteTask = false + 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" + + slowSoundResourceId = soundPool.load(this, R.raw.ring4, 1) + fastSoundResourceId = soundPool.load(this, R.raw.ring2, 1) + + //点位渲染,每次定位都计算当前位置与符合条件的点距离 + locationKit.getCurrentLocation(false, object : OnGetLocationListener { + override fun onSuccess(location: AMapLocation) { + renderDataPoint(location) + } + + override fun onError() { + "当前位置信号差,无法获取定位".show(context) + } + }) + + if (isExecuteTask) { + binding.taskStateView.visibility = View.GONE + binding.taskStateView.isSelected = false + } else { + binding.taskStateView.visibility = View.VISIBLE + binding.taskStateView.isSelected = true + } + + //进入界面开始搜索信号强度 + sendSerialPortCommand(SerialPortCommand.SEARCH_SIGNAL) + } + + private val handler = Handler(Looper.getMainLooper()) + private var detectDepthRunnable: DetectDepthRunnable? = null + + private inner class DetectDepthRunnable(private val command: Int) : Runnable { + override fun run() { + sendSerialPortCommand(command) + //延迟三秒再发一次 + handler.postDelayed(this, 3000) + } + } + + override fun initEvent() { + binding.depthButton.setOnClickListener { + if (detectedMarkerId == "") { + //还没探测到,直接显示当初埋深 + val result = markerBeanDao.queryMarkerById(databaseMarkerId) + val depth = if (result.isNotEmpty()) { + "110厘米" + } else { + result.first().markerDepth + } + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("温馨提示") + .setMessage("标识器埋深:$depth") + .setPositiveButton("知道了") + .setOnDialogButtonClickListener(object : + AlertMessageDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + RuntimeCache.currentSegment = CurrentSegment.SearchMarker + sendSerialPortCommand(SerialPortCommand.SEARCH_SIGNAL) + } + }).build().show() + return@setOnClickListener + } + + //真实探测埋深 + RuntimeCache.currentSegment = CurrentSegment.DetectDepth + val result = markerBeanDao.queryMarkerById(detectedMarkerId) + if (result.isNotEmpty()) { + 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 (command == SerialPortCommand.STOP_SERIAL_PORT_DATA) { + "此标识器无法读取埋深!".show(this) + } else { + soundPool.autoPause() + LoadingDialog.show(this, "正在探测标识器埋深,请稍后...") + + // 移除之前的 Runnable(如果存在) + detectDepthRunnable?.let { handler.removeCallbacks(it) } + detectDepthRunnable = DetectDepthRunnable(command) + // 发送读取标识器埋设深度指令 + handler.post(detectDepthRunnable!!) + } + } else { + "标识器未安装,安装成功后才可读取埋深!".show(this) + } + } + + binding.markerIdButton.setOnClickListener { + sendSerialPortCommand(SerialPortCommand.SEARCH_MARKER_ALWAYS) + } + + binding.markerInfoButton.setOnClickListener { + val markerId = if (detectedMarkerId == "") { + databaseMarkerId + } else { + detectedMarkerId + } + val result = markerBeanDao.queryMarkerById(markerId) + if (result.isNotEmpty()) { + MarkerDetailDialog(this).setMarker(result.first()).show() + } else { + NewMarkerDetailDialog(this, markerId) + } + //查询完之后重置ID,以便下次重走逻辑 + databaseMarkerId = "" + detectedMarkerId = "" + } + } + + override fun onMarkerIdDetected(markerId: String) { + if (RuntimeCache.currentSegment == CurrentSegment.SearchMarker) { + binding.depthButton.isEnabled = true + binding.depthButton.setTextColor(Color.WHITE) + binding.depthButton.backgroundTintList = + ColorStateList.valueOf("#004364".toColorInt()) + + binding.markerInfoButton.isEnabled = true + binding.markerInfoButton.setTextColor(Color.WHITE) + binding.markerInfoButton.backgroundTintList = + ColorStateList.valueOf("#FFA200".toColorInt()) + + handleMarker(markerId) + } + } + + private fun handleMarker(id: String) { + detectedMarkerId = id + //自动上传标识器 + if (isExecuteTask) { + val taskId = SaveKeyValues.getValue(LocaleConstant.TASK_ID, "") as String + val taskCode = SaveKeyValues.getValue(LocaleConstant.TASK_CODE, "") as String + val marker = taskMarkerBeanDao.queryTaskMarkerById( + taskId, taskCode, id, "0" + ) + if (marker == null) { + return + } + taskViewModel.uploadMarker( + marker.markerId, + onLoading = {}, + onSuccess = { + "标识器${marker.markerId}已探测!".show(this) + marker.isDetected = "1" + taskMarkerBeanDao.updateLocalTaskMarkerState(marker) + }, + onFailed = {} + ) + } + } + + override fun onMarkerDepthDetected(depth: Int) { + if (RuntimeCache.currentSegment == CurrentSegment.DetectDepth) { + detectDepthRunnable?.let { handler.removeCallbacks(it) } + detectDepthRunnable = null + LoadingDialog.dismiss() + if (!this.isDestroyed) { + 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() + } else { + "标识器埋深:${depth}厘米".show(this) + } + } + } + + override fun onMarkerSignalDetected(signalEnergy: Int) { + if (RuntimeCache.currentSegment == CurrentSegment.SearchMarker) { + if (signalEnergy > 1000) { + binding.markerIdButton.isEnabled = true + binding.markerIdButton.setTextColor("#428d00".toColorInt()) + binding.markerIdButton.backgroundTintList = ColorStateList.valueOf( + "#7EFF00".toColorInt() + ) + + binding.searchResultView.text = "已检测到标识器" + binding.searchResultView.setTextColor("#428d00".toColorInt()) + 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) { + when { + signalEnergy <= 700 -> { + setEnergyTip( + "信号较弱,可能距离较远", + "#8D1717".toColorInt(), + R.mipmap.bg_large_text_red + ) + binding.searchResultView.text = "未检测到标识器" + binding.searchResultView.setTextColor("#8D1717".toColorInt()) + binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_red) + } + + signalEnergy >= 4100 -> { + setEnergyTip( + "信号极强,接近标识器正上方", + "#428d00".toColorInt(), + R.mipmap.bg_large_text_green + ) + } + + else -> { + setEnergyTip( + "已靠近,请继续移动位置", + "#8C5700".toColorInt(), + R.mipmap.bg_large_text_yellow + ) + } + } + } + + private fun setEnergyTip(text: String, textColorRes: Int, backgroundRes: Int) { + binding.energyTipsView.text = text + binding.energyTipsView.setTextColor(textColorRes) + binding.energyTipsView.setBackgroundResource(backgroundRes) + } + + /** + * 计算并渲染数据点。点太多采用协程计算,不然会有点卡顿。默认2s计算一次 + * @param location 定位点(RTK获取) + * */ + private fun renderDataPoint(location: AMapLocation) { + val longitude = location.longitude + val latitude = location.latitude + lifecycleScope.launch(Dispatchers.IO) { + val dataPoints = ArrayList() + markerBeanDao.loadAll().forEach { + val distance = AMapUtils.calculateLineDistance( + LatLng(it.lat.toDouble(), it.lng.toDouble()), LatLng(latitude, longitude) + ) + val formatDistance = "%.2f".format(distance).toFloat() + markerPoints.add(MarkerDistanceData(it.markerId, formatDistance)) + + if (formatDistance <= LocaleConstant.MAX_DISTANCE) { + val angle = atan2( + (it.lat.toDouble() - latitude), (it.lng.toDouble() - longitude) + ) + Math.PI + val formatAngle = "%.2f".format(angle).toDouble() + + dataPoints.add( + RadarScanView.DataPoint(it.markerId, formatAngle, formatDistance) + ) + } + } + withContext(Dispatchers.Main) { + binding.radarScanView.renderPointData( + dataPoints, + onGetNearestPoint = { point -> + if (point == null) { + binding.distanceValueView.text = "大于5.5m" + binding.distancePgBar.progress = 100 + } else { + databaseMarkerId = point.markerId + + binding.depthButton.isEnabled = true + binding.depthButton.setTextColor(Color.WHITE) + binding.depthButton.backgroundTintList = + ColorStateList.valueOf("#004364".toColorInt()) + + binding.markerInfoButton.isEnabled = true + binding.markerInfoButton.setTextColor(Color.WHITE) + binding.markerInfoButton.backgroundTintList = + ColorStateList.valueOf("#FFA200".toColorInt()) + + binding.distanceValueView.text = "${point.distance}m" + val progress = if (point.distance > LocaleConstant.MAX_DISTANCE) { + 100 + } else { + (point.distance / LocaleConstant.MAX_DISTANCE) * 100 + } + binding.distancePgBar.progress = progress.toInt() + } + } + ) + } + } + } + + override fun initViewBinding(): ActivitySearchMarkerBinding { + return ActivitySearchMarkerBinding.inflate(layoutInflater) + } + + override fun setupTopBarLayout() { + + } + + override fun onResume() { + super.onResume() + //注册加速度传感器监听 + val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) + sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL) + + //注册磁场传感器监听 + val magnetic = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) + sensorManager.registerListener(this, magnetic, SensorManager.SENSOR_DELAY_NORMAL) + } + + override fun onPause() { + super.onPause() + sensorManager.unregisterListener(this) + } + + override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) { + //精度发生变化时触发 + } + + override fun onSensorChanged(event: SensorEvent?) { + //值发生变化时触发 + val type = event?.sensor?.type + + if (type == Sensor.TYPE_ACCELEROMETER) { + gravity = event.values + } else if (type == Sensor.TYPE_MAGNETIC_FIELD) { + geomagnetic = event.values + } + + if (gravity == null || geomagnetic == null) { + return + } + + if (SensorManager.getRotationMatrix(rotationMatrix, null, gravity, geomagnetic)) { + SensorManager.getOrientation(rotationMatrix, valueArray) + + val degree = ((360f + valueArray[0] * 180f / Math.PI) % 360).toInt() + //更新罗盘角度 + binding.radarScanView.setDegreeValue(degree) + } + } + + override fun onDestroy() { + super.onDestroy() + soundPool.autoPause() + locationKit.stopLocation() + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 904657b..739ca8a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -62,7 +62,6 @@ - diff --git "a/app/src/main/assets/SearchMarkerActivity - \346\274\224\347\244\272\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" "b/app/src/main/assets/SearchMarkerActivity - \346\274\224\347\244\272\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" deleted file mode 100644 index b3e68e3..0000000 --- "a/app/src/main/assets/SearchMarkerActivity - \346\274\224\347\244\272\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" +++ /dev/null @@ -1,447 +0,0 @@ -import android.content.res.ColorStateList -import android.graphics.Color -import android.hardware.Sensor -import android.hardware.SensorEvent -import android.hardware.SensorEventListener -import android.hardware.SensorManager -import android.media.AudioAttributes -import android.media.SoundPool -import android.os.Bundle -import android.os.Handler -import android.os.Looper -import android.view.View -import androidx.core.graphics.toColorInt -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.BaseApplication -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.model.MarkerDistanceData -import com.casic.common.detector.gd.utils.CurrentSegment -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.MarkerDetailDialog -import com.casic.common.detector.gd.widgets.NewMarkerDetailDialog -import com.casic.common.detector.gd.widgets.RadarScanView -import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.utils.LiteKitConstant -import com.pengxh.kt.lite.utils.LoadingDialog -import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import kotlin.math.atan2 - -class SearchMarkerActivity : SerialPortBaseActivity(), - SensorEventListener { - - private val kTag = "SearchMarkerActivity" - private val context = this - private val locationKit by lazy { LocationKit(this) } - private val markerPoints by lazy { ArrayList() } - private val markerBeanDao by lazy { BaseApplication.get().dataBase.markerBeanDao() } - private val taskMarkerBeanDao by lazy { BaseApplication.get().dataBase.taskMarkerBeanDao() } - private val taskViewModel by lazy { ViewModelProvider(this)[TaskViewModel::class.java] } - private val sensorManager by lazy { getSystemService(SENSOR_SERVICE) as SensorManager } - private val attr = AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ALARM) - .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build() - private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build() - private val rotationMatrix = FloatArray(9)//旋转矩阵缓存 - private val valueArray = FloatArray(3)//方位角数值 - private var slowSoundResourceId = 0 - private var fastSoundResourceId = 0 - private var databaseMarkerId = ""//本地数据库标识器ID - private var detectedMarkerId = ""//真实探测到标识器ID - private var isExecuteTask = false - 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" - - slowSoundResourceId = soundPool.load(this, R.raw.ring4, 1) - fastSoundResourceId = soundPool.load(this, R.raw.ring2, 1) - - //点位渲染,每次定位都计算当前位置与符合条件的点距离 - locationKit.getCurrentLocation(false, object : OnGetLocationListener { - override fun onSuccess(location: AMapLocation) { - renderDataPoint(location) - } - - override fun onError() { - "当前位置信号差,无法获取定位".show(context) - } - }) - - if (isExecuteTask) { - binding.taskStateView.visibility = View.GONE - binding.taskStateView.isSelected = false - } else { - binding.taskStateView.visibility = View.VISIBLE - binding.taskStateView.isSelected = true - } - - //进入界面开始搜索信号强度 - sendSerialPortCommand(SerialPortCommand.SEARCH_SIGNAL) - } - - private val handler = Handler(Looper.getMainLooper()) - private var detectDepthRunnable: DetectDepthRunnable? = null - - private inner class DetectDepthRunnable(private val command: Int) : Runnable { - override fun run() { - sendSerialPortCommand(command) - //延迟三秒再发一次 - handler.postDelayed(this, 3000) - } - } - - override fun initEvent() { - binding.depthButton.setOnClickListener { - if (detectedMarkerId == "") { - //还没探测到,直接显示当初埋深 - val result = markerBeanDao.queryMarkerById(databaseMarkerId) - val depth = if (result.isNotEmpty()) { - "110厘米" - } else { - result.first().markerDepth - } - AlertMessageDialog.Builder() - .setContext(this) - .setTitle("温馨提示") - .setMessage("标识器埋深:$depth") - .setPositiveButton("知道了") - .setOnDialogButtonClickListener(object : - AlertMessageDialog.OnDialogButtonClickListener { - override fun onConfirmClick() { - RuntimeCache.currentSegment = CurrentSegment.SearchMarker - sendSerialPortCommand(SerialPortCommand.SEARCH_SIGNAL) - } - }).build().show() - return@setOnClickListener - } - - //真实探测埋深 - RuntimeCache.currentSegment = CurrentSegment.DetectDepth - val result = markerBeanDao.queryMarkerById(detectedMarkerId) - if (result.isNotEmpty()) { - 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 (command == SerialPortCommand.STOP_SERIAL_PORT_DATA) { - "此标识器无法读取埋深!".show(this) - } else { - soundPool.autoPause() - LoadingDialog.show(this, "正在探测标识器埋深,请稍后...") - - // 移除之前的 Runnable(如果存在) - detectDepthRunnable?.let { handler.removeCallbacks(it) } - detectDepthRunnable = DetectDepthRunnable(command) - // 发送读取标识器埋设深度指令 - handler.post(detectDepthRunnable!!) - } - } else { - "标识器未安装,安装成功后才可读取埋深!".show(this) - } - } - - binding.markerIdButton.setOnClickListener { - sendSerialPortCommand(SerialPortCommand.SEARCH_MARKER_ALWAYS) - } - - binding.markerInfoButton.setOnClickListener { - val markerId = if (detectedMarkerId == "") { - databaseMarkerId - } else { - detectedMarkerId - } - val result = markerBeanDao.queryMarkerById(markerId) - if (result.isNotEmpty()) { - MarkerDetailDialog(this).setMarker(result.first()).show() - } else { - NewMarkerDetailDialog(this, markerId) - } - //查询完之后重置ID,以便下次重走逻辑 - databaseMarkerId = "" - detectedMarkerId = "" - } - } - - override fun onMarkerIdDetected(markerId: String) { - if (RuntimeCache.currentSegment == CurrentSegment.SearchMarker) { - binding.depthButton.isEnabled = true - binding.depthButton.setTextColor(Color.WHITE) - binding.depthButton.backgroundTintList = - ColorStateList.valueOf("#004364".toColorInt()) - - binding.markerInfoButton.isEnabled = true - binding.markerInfoButton.setTextColor(Color.WHITE) - binding.markerInfoButton.backgroundTintList = - ColorStateList.valueOf("#FFA200".toColorInt()) - - handleMarker(markerId) - } - } - - private fun handleMarker(id: String) { - detectedMarkerId = id - //自动上传标识器 - if (isExecuteTask) { - val taskId = SaveKeyValues.getValue(LocaleConstant.TASK_ID, "") as String - val taskCode = SaveKeyValues.getValue(LocaleConstant.TASK_CODE, "") as String - val marker = taskMarkerBeanDao.queryTaskMarkerById( - taskId, taskCode, id, "0" - ) - if (marker == null) { - return - } - taskViewModel.uploadMarker( - marker.markerId, - onLoading = {}, - onSuccess = { - "标识器${marker.markerId}已探测!".show(this) - marker.isDetected = "1" - taskMarkerBeanDao.updateLocalTaskMarkerState(marker) - }, - onFailed = {} - ) - } - } - - override fun onMarkerDepthDetected(depth: Int) { - if (RuntimeCache.currentSegment == CurrentSegment.DetectDepth) { - detectDepthRunnable?.let { handler.removeCallbacks(it) } - detectDepthRunnable = null - LoadingDialog.dismiss() - if (!this.isDestroyed) { - 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() - } else { - "标识器埋深:${depth}厘米".show(this) - } - } - } - - override fun onMarkerSignalDetected(signalEnergy: Int) { - if (RuntimeCache.currentSegment == CurrentSegment.SearchMarker) { - if (signalEnergy > 1000) { - binding.markerIdButton.isEnabled = true - binding.markerIdButton.setTextColor("#428d00".toColorInt()) - binding.markerIdButton.backgroundTintList = ColorStateList.valueOf( - "#7EFF00".toColorInt() - ) - - binding.searchResultView.text = "已检测到标识器" - binding.searchResultView.setTextColor("#428d00".toColorInt()) - 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) { - when { - signalEnergy <= 700 -> { - setEnergyTip( - "信号较弱,可能距离较远", - "#8D1717".toColorInt(), - R.mipmap.bg_large_text_red - ) -// disableButtons() - binding.searchResultView.text = "未检测到标识器" - binding.searchResultView.setTextColor("#8D1717".toColorInt()) - binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_red) - } - - signalEnergy >= 4100 -> { - setEnergyTip( - "信号极强,接近标识器正上方", - "#428d00".toColorInt(), - R.mipmap.bg_large_text_green - ) - } - - else -> { - setEnergyTip( - "已靠近,请继续移动位置", - "#8C5700".toColorInt(), - R.mipmap.bg_large_text_yellow - ) - } - } - } - - private fun setEnergyTip(text: String, textColorRes: Int, backgroundRes: Int) { - binding.energyTipsView.text = text - binding.energyTipsView.setTextColor(textColorRes) - binding.energyTipsView.setBackgroundResource(backgroundRes) - } - - private val colorStateList = ColorStateList.valueOf("#8A8A8A".toColorInt()) - private val textColor = "#CCCCCC".toColorInt() - - private fun disableButtons() { - binding.depthButton.isEnabled = false - 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(textColor) - binding.markerInfoButton.backgroundTintList = colorStateList - } - - /** - * 计算并渲染数据点。点太多采用协程计算,不然会有点卡顿。默认2s计算一次 - * @param location 定位点(RTK获取) - * */ - private fun renderDataPoint(location: AMapLocation) { - val longitude = location.longitude - val latitude = location.latitude - lifecycleScope.launch(Dispatchers.IO) { - val dataPoints = ArrayList() - markerBeanDao.loadAll().forEach { - val distance = AMapUtils.calculateLineDistance( - LatLng(it.lat.toDouble(), it.lng.toDouble()), LatLng(latitude, longitude) - ) - val formatDistance = "%.2f".format(distance).toFloat() - markerPoints.add(MarkerDistanceData(it.markerId, formatDistance)) - - if (formatDistance <= LocaleConstant.MAX_DISTANCE) { - val angle = atan2( - (it.lat.toDouble() - latitude), (it.lng.toDouble() - longitude) - ) + Math.PI - val formatAngle = "%.2f".format(angle).toDouble() - - dataPoints.add( - RadarScanView.DataPoint(it.markerId, formatAngle, formatDistance) - ) - } - } - withContext(Dispatchers.Main) { - binding.radarScanView.renderPointData( - dataPoints, - onGetNearestPoint = { point -> - if (point == null) { - binding.distanceValueView.text = "大于5.5m" - binding.distancePgBar.progress = 100 - } else { - databaseMarkerId = point.markerId - - binding.depthButton.isEnabled = true - binding.depthButton.setTextColor(Color.WHITE) - binding.depthButton.backgroundTintList = - ColorStateList.valueOf("#004364".toColorInt()) - - binding.markerInfoButton.isEnabled = true - binding.markerInfoButton.setTextColor(Color.WHITE) - binding.markerInfoButton.backgroundTintList = - ColorStateList.valueOf("#FFA200".toColorInt()) - - binding.distanceValueView.text = "${point.distance}m" - val progress = if (point.distance > LocaleConstant.MAX_DISTANCE) { - 100 - } else { - (point.distance / LocaleConstant.MAX_DISTANCE) * 100 - } - binding.distancePgBar.progress = progress.toInt() - } - } - ) - } - } - } - - override fun initViewBinding(): ActivitySearchMarkerBinding { - return ActivitySearchMarkerBinding.inflate(layoutInflater) - } - - override fun setupTopBarLayout() { - - } - - override fun onResume() { - super.onResume() - //注册加速度传感器监听 - val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) - sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL) - - //注册磁场传感器监听 - val magnetic = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) - sensorManager.registerListener(this, magnetic, SensorManager.SENSOR_DELAY_NORMAL) - } - - override fun onPause() { - super.onPause() - sensorManager.unregisterListener(this) - } - - override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) { - //精度发生变化时触发 - } - - override fun onSensorChanged(event: SensorEvent?) { - //值发生变化时触发 - val type = event?.sensor?.type - - if (type == Sensor.TYPE_ACCELEROMETER) { - gravity = event.values - } else if (type == Sensor.TYPE_MAGNETIC_FIELD) { - geomagnetic = event.values - } - - if (gravity == null || geomagnetic == null) { - return - } - - if (SensorManager.getRotationMatrix(rotationMatrix, null, gravity, geomagnetic)) { - SensorManager.getOrientation(rotationMatrix, valueArray) - - val degree = ((360f + valueArray[0] * 180f / Math.PI) % 360).toInt() - //更新罗盘角度 - binding.radarScanView.setDegreeValue(degree) - } - } - - override fun onDestroy() { - super.onDestroy() - soundPool.autoPause() - locationKit.stopLocation() - } -} \ No newline at end of file diff --git "a/app/src/main/assets/\345\256\241\350\256\241\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" "b/app/src/main/assets/\345\256\241\350\256\241\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" new file mode 100644 index 0000000..c4af67a --- /dev/null +++ "b/app/src/main/assets/\345\256\241\350\256\241\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" @@ -0,0 +1,189 @@ +import android.hardware.Sensor +import android.hardware.SensorEvent +import android.hardware.SensorEventListener +import android.hardware.SensorManager +import android.media.AudioAttributes +import android.media.SoundPool +import android.os.Bundle +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.BaseApplication +import com.casic.common.detector.gd.callback.OnGetLocationListener +import com.casic.common.detector.gd.databinding.ActivitySearchMarkerAuditBinding +import com.casic.common.detector.gd.utils.LocaleConstant +import com.casic.common.detector.gd.utils.LocationKit +import com.casic.common.detector.gd.widgets.MarkerDetailDialog +import com.casic.common.detector.gd.widgets.NewMarkerDetailDialog +import com.casic.common.detector.gd.widgets.RadarScanView +import com.pengxh.kt.lite.base.KotlinBaseActivity +import com.pengxh.kt.lite.extensions.show +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 : KotlinBaseActivity(), + SensorEventListener { + + private val kTag = "SearchMarkerActivity" + private val context = this + private val locationKit by lazy { LocationKit(this) } + private val sensorManager by lazy { getSystemService(SENSOR_SERVICE) as SensorManager } + private val markerBeanDao by lazy { BaseApplication.Companion.get().dataBase.markerBeanDao() } + private val attr = AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ALARM) + .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build() + private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build() + private val rotationMatrix = FloatArray(9)//旋转矩阵缓存 + private val valueArray = FloatArray(3)//方位角数值 + private var nearestMarkerId = ""//探测不到标识器的时候计算出来的最近的标识器ID + private var gravity: FloatArray? = null + private var geomagnetic: FloatArray? = null + private lateinit var searchSignalEnergyTimer: Timer + + override fun initOnCreate(savedInstanceState: Bundle?) { + val fastSoundResourceId = soundPool.load(this, R.raw.ring2, 1) + + //点位渲染,每次定位都计算当前位置与符合条件的点距离 + locationKit.getCurrentLocation(false, object : OnGetLocationListener { + override fun onSuccess(location: AMapLocation) { + renderDataPoint(location) + } + + override fun onError() { + "当前位置信号差,无法获取定位".show(context) + } + }) + + searchSignalEnergyTimer = Timer() + searchSignalEnergyTimer.schedule(object : TimerTask() { + override fun run() { + soundPool.play(fastSoundResourceId, 1f, 1f, 0, 0, 1f) + } + }, 0, 100) + } + + override fun initEvent() { + binding.markerInfoButton.setOnClickListener { + //查库 + val result = markerBeanDao.queryMarkerById(nearestMarkerId) + if (result.isNotEmpty()) { + MarkerDetailDialog(this).setMarker(result.first()).show() + } else { + NewMarkerDetailDialog(this, nearestMarkerId) + } + } + } + + /** + * 计算并渲染数据点。点太多采用协程计算,不然会有点卡顿。默认2s计算一次 + * @param location 定位点(RTK获取) + * */ + private fun renderDataPoint(location: AMapLocation) { + val longitude = location.longitude + val latitude = location.latitude + lifecycleScope.launch(Dispatchers.IO) { + val dataPoints = ArrayList() + markerBeanDao.loadAll().forEach { + val distance = AMapUtils.calculateLineDistance( + LatLng(it.lat.toDouble(), it.lng.toDouble()), LatLng(latitude, longitude) + ) + val formatDistance = "%.2f".format(distance).toFloat() + val angle = atan2( + (it.lat.toDouble() - latitude), (it.lng.toDouble() - longitude) + ) + Math.PI + val formatAngle = "%.2f".format(angle).toDouble() + + dataPoints.add( + RadarScanView.DataPoint(it.markerId, formatAngle, formatDistance) + ) + } + withContext(Dispatchers.Main) { + binding.radarScanView.renderPointData( + dataPoints, + onGetNearestPoint = { point -> + if (point == null) { + binding.distanceValueView.text = "大于5.5m" + binding.distancePgBar.progress = 100 + } else { + nearestMarkerId = point.markerId + binding.distanceValueView.text = "${point.distance}m" + val progress = if (point.distance > LocaleConstant.MAX_DISTANCE) { + 100 + } else { + (point.distance / LocaleConstant.MAX_DISTANCE) * 100 + } + binding.distancePgBar.progress = progress.toInt() + } + } + ) + } + } + } + + override fun initViewBinding(): ActivitySearchMarkerAuditBinding { + return ActivitySearchMarkerAuditBinding.inflate(layoutInflater) + } + + override fun observeRequestState() { + + } + + override fun setupTopBarLayout() { + + } + + override fun onResume() { + super.onResume() + //注册加速度传感器监听 + val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) + sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL) + + //注册磁场传感器监听 + val magnetic = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) + sensorManager.registerListener(this, magnetic, SensorManager.SENSOR_DELAY_NORMAL) + } + + override fun onPause() { + super.onPause() + sensorManager.unregisterListener(this) + } + + override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) { + //精度发生变化时触发 + } + + override fun onSensorChanged(event: SensorEvent?) { + //值发生变化时触发 + val type = event?.sensor?.type + + if (type == Sensor.TYPE_ACCELEROMETER) { + gravity = event.values + } else if (type == Sensor.TYPE_MAGNETIC_FIELD) { + geomagnetic = event.values + } + + if (gravity == null || geomagnetic == null) { + return + } + + if (SensorManager.getRotationMatrix(rotationMatrix, null, gravity, geomagnetic)) { + SensorManager.getOrientation(rotationMatrix, valueArray) + + val degree = ((360f + valueArray[0] * 180f / Math.PI) % 360).toInt() + //更新罗盘角度 + binding.radarScanView.setDegreeValue(degree) + } + } + + override fun onDestroy() { + super.onDestroy() + searchSignalEnergyTimer.cancel() + soundPool.release() + locationKit.stopLocation() + } +} \ No newline at end of file diff --git "a/app/src/main/assets/\346\274\224\347\244\272\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" "b/app/src/main/assets/\346\274\224\347\244\272\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" new file mode 100644 index 0000000..597b2cd --- /dev/null +++ "b/app/src/main/assets/\346\274\224\347\244\272\347\211\210\344\273\243\347\240\201\345\244\207\344\273\275.kt" @@ -0,0 +1,431 @@ +import android.content.res.ColorStateList +import android.graphics.Color +import android.hardware.Sensor +import android.hardware.SensorEvent +import android.hardware.SensorEventListener +import android.hardware.SensorManager +import android.media.AudioAttributes +import android.media.SoundPool +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.view.View +import androidx.core.graphics.toColorInt +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.BaseApplication +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.model.MarkerDistanceData +import com.casic.common.detector.gd.utils.CurrentSegment +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.MarkerDetailDialog +import com.casic.common.detector.gd.widgets.NewMarkerDetailDialog +import com.casic.common.detector.gd.widgets.RadarScanView +import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LiteKitConstant +import com.pengxh.kt.lite.utils.LoadingDialog +import com.pengxh.kt.lite.utils.SaveKeyValues +import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import kotlin.math.atan2 + +class SearchMarkerActivity : SerialPortBaseActivity(), + SensorEventListener { + + private val kTag = "SearchMarkerActivity" + private val context = this + private val locationKit by lazy { LocationKit(this) } + private val markerPoints by lazy { ArrayList() } + private val markerBeanDao by lazy { BaseApplication.get().dataBase.markerBeanDao() } + private val taskMarkerBeanDao by lazy { BaseApplication.get().dataBase.taskMarkerBeanDao() } + private val taskViewModel by lazy { ViewModelProvider(this)[TaskViewModel::class.java] } + private val sensorManager by lazy { getSystemService(SENSOR_SERVICE) as SensorManager } + private val attr = AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ALARM) + .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build() + private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build() + private val rotationMatrix = FloatArray(9)//旋转矩阵缓存 + private val valueArray = FloatArray(3)//方位角数值 + private var slowSoundResourceId = 0 + private var fastSoundResourceId = 0 + private var databaseMarkerId = ""//本地数据库标识器ID + private var detectedMarkerId = ""//真实探测到标识器ID + private var isExecuteTask = false + 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" + + slowSoundResourceId = soundPool.load(this, R.raw.ring4, 1) + fastSoundResourceId = soundPool.load(this, R.raw.ring2, 1) + + //点位渲染,每次定位都计算当前位置与符合条件的点距离 + locationKit.getCurrentLocation(false, object : OnGetLocationListener { + override fun onSuccess(location: AMapLocation) { + renderDataPoint(location) + } + + override fun onError() { + "当前位置信号差,无法获取定位".show(context) + } + }) + + if (isExecuteTask) { + binding.taskStateView.visibility = View.GONE + binding.taskStateView.isSelected = false + } else { + binding.taskStateView.visibility = View.VISIBLE + binding.taskStateView.isSelected = true + } + + //进入界面开始搜索信号强度 + sendSerialPortCommand(SerialPortCommand.SEARCH_SIGNAL) + } + + private val handler = Handler(Looper.getMainLooper()) + private var detectDepthRunnable: DetectDepthRunnable? = null + + private inner class DetectDepthRunnable(private val command: Int) : Runnable { + override fun run() { + sendSerialPortCommand(command) + //延迟三秒再发一次 + handler.postDelayed(this, 3000) + } + } + + override fun initEvent() { + binding.depthButton.setOnClickListener { + if (detectedMarkerId == "") { + //还没探测到,直接显示当初埋深 + val result = markerBeanDao.queryMarkerById(databaseMarkerId) + val depth = if (result.isNotEmpty()) { + "110厘米" + } else { + result.first().markerDepth + } + AlertMessageDialog.Builder() + .setContext(this) + .setTitle("温馨提示") + .setMessage("标识器埋深:$depth") + .setPositiveButton("知道了") + .setOnDialogButtonClickListener(object : + AlertMessageDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + RuntimeCache.currentSegment = CurrentSegment.SearchMarker + sendSerialPortCommand(SerialPortCommand.SEARCH_SIGNAL) + } + }).build().show() + return@setOnClickListener + } + + //真实探测埋深 + RuntimeCache.currentSegment = CurrentSegment.DetectDepth + val result = markerBeanDao.queryMarkerById(detectedMarkerId) + if (result.isNotEmpty()) { + 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 (command == SerialPortCommand.STOP_SERIAL_PORT_DATA) { + "此标识器无法读取埋深!".show(this) + } else { + soundPool.autoPause() + LoadingDialog.show(this, "正在探测标识器埋深,请稍后...") + + // 移除之前的 Runnable(如果存在) + detectDepthRunnable?.let { handler.removeCallbacks(it) } + detectDepthRunnable = DetectDepthRunnable(command) + // 发送读取标识器埋设深度指令 + handler.post(detectDepthRunnable!!) + } + } else { + "标识器未安装,安装成功后才可读取埋深!".show(this) + } + } + + binding.markerIdButton.setOnClickListener { + sendSerialPortCommand(SerialPortCommand.SEARCH_MARKER_ALWAYS) + } + + binding.markerInfoButton.setOnClickListener { + val markerId = if (detectedMarkerId == "") { + databaseMarkerId + } else { + detectedMarkerId + } + val result = markerBeanDao.queryMarkerById(markerId) + if (result.isNotEmpty()) { + MarkerDetailDialog(this).setMarker(result.first()).show() + } else { + NewMarkerDetailDialog(this, markerId) + } + //查询完之后重置ID,以便下次重走逻辑 + databaseMarkerId = "" + detectedMarkerId = "" + } + } + + override fun onMarkerIdDetected(markerId: String) { + if (RuntimeCache.currentSegment == CurrentSegment.SearchMarker) { + binding.depthButton.isEnabled = true + binding.depthButton.setTextColor(Color.WHITE) + binding.depthButton.backgroundTintList = + ColorStateList.valueOf("#004364".toColorInt()) + + binding.markerInfoButton.isEnabled = true + binding.markerInfoButton.setTextColor(Color.WHITE) + binding.markerInfoButton.backgroundTintList = + ColorStateList.valueOf("#FFA200".toColorInt()) + + handleMarker(markerId) + } + } + + private fun handleMarker(id: String) { + detectedMarkerId = id + //自动上传标识器 + if (isExecuteTask) { + val taskId = SaveKeyValues.getValue(LocaleConstant.TASK_ID, "") as String + val taskCode = SaveKeyValues.getValue(LocaleConstant.TASK_CODE, "") as String + val marker = taskMarkerBeanDao.queryTaskMarkerById( + taskId, taskCode, id, "0" + ) + if (marker == null) { + return + } + taskViewModel.uploadMarker( + marker.markerId, + onLoading = {}, + onSuccess = { + "标识器${marker.markerId}已探测!".show(this) + marker.isDetected = "1" + taskMarkerBeanDao.updateLocalTaskMarkerState(marker) + }, + onFailed = {} + ) + } + } + + override fun onMarkerDepthDetected(depth: Int) { + if (RuntimeCache.currentSegment == CurrentSegment.DetectDepth) { + detectDepthRunnable?.let { handler.removeCallbacks(it) } + detectDepthRunnable = null + LoadingDialog.dismiss() + if (!this.isDestroyed) { + 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() + } else { + "标识器埋深:${depth}厘米".show(this) + } + } + } + + override fun onMarkerSignalDetected(signalEnergy: Int) { + if (RuntimeCache.currentSegment == CurrentSegment.SearchMarker) { + if (signalEnergy > 1000) { + binding.markerIdButton.isEnabled = true + binding.markerIdButton.setTextColor("#428d00".toColorInt()) + binding.markerIdButton.backgroundTintList = ColorStateList.valueOf( + "#7EFF00".toColorInt() + ) + + binding.searchResultView.text = "已检测到标识器" + binding.searchResultView.setTextColor("#428d00".toColorInt()) + 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) { + when { + signalEnergy <= 700 -> { + setEnergyTip( + "信号较弱,可能距离较远", + "#8D1717".toColorInt(), + R.mipmap.bg_large_text_red + ) + binding.searchResultView.text = "未检测到标识器" + binding.searchResultView.setTextColor("#8D1717".toColorInt()) + binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_red) + } + + signalEnergy >= 4100 -> { + setEnergyTip( + "信号极强,接近标识器正上方", + "#428d00".toColorInt(), + R.mipmap.bg_large_text_green + ) + } + + else -> { + setEnergyTip( + "已靠近,请继续移动位置", + "#8C5700".toColorInt(), + R.mipmap.bg_large_text_yellow + ) + } + } + } + + private fun setEnergyTip(text: String, textColorRes: Int, backgroundRes: Int) { + binding.energyTipsView.text = text + binding.energyTipsView.setTextColor(textColorRes) + binding.energyTipsView.setBackgroundResource(backgroundRes) + } + + /** + * 计算并渲染数据点。点太多采用协程计算,不然会有点卡顿。默认2s计算一次 + * @param location 定位点(RTK获取) + * */ + private fun renderDataPoint(location: AMapLocation) { + val longitude = location.longitude + val latitude = location.latitude + lifecycleScope.launch(Dispatchers.IO) { + val dataPoints = ArrayList() + markerBeanDao.loadAll().forEach { + val distance = AMapUtils.calculateLineDistance( + LatLng(it.lat.toDouble(), it.lng.toDouble()), LatLng(latitude, longitude) + ) + val formatDistance = "%.2f".format(distance).toFloat() + markerPoints.add(MarkerDistanceData(it.markerId, formatDistance)) + + if (formatDistance <= LocaleConstant.MAX_DISTANCE) { + val angle = atan2( + (it.lat.toDouble() - latitude), (it.lng.toDouble() - longitude) + ) + Math.PI + val formatAngle = "%.2f".format(angle).toDouble() + + dataPoints.add( + RadarScanView.DataPoint(it.markerId, formatAngle, formatDistance) + ) + } + } + withContext(Dispatchers.Main) { + binding.radarScanView.renderPointData( + dataPoints, + onGetNearestPoint = { point -> + if (point == null) { + binding.distanceValueView.text = "大于5.5m" + binding.distancePgBar.progress = 100 + } else { + databaseMarkerId = point.markerId + + binding.depthButton.isEnabled = true + binding.depthButton.setTextColor(Color.WHITE) + binding.depthButton.backgroundTintList = + ColorStateList.valueOf("#004364".toColorInt()) + + binding.markerInfoButton.isEnabled = true + binding.markerInfoButton.setTextColor(Color.WHITE) + binding.markerInfoButton.backgroundTintList = + ColorStateList.valueOf("#FFA200".toColorInt()) + + binding.distanceValueView.text = "${point.distance}m" + val progress = if (point.distance > LocaleConstant.MAX_DISTANCE) { + 100 + } else { + (point.distance / LocaleConstant.MAX_DISTANCE) * 100 + } + binding.distancePgBar.progress = progress.toInt() + } + } + ) + } + } + } + + override fun initViewBinding(): ActivitySearchMarkerBinding { + return ActivitySearchMarkerBinding.inflate(layoutInflater) + } + + override fun setupTopBarLayout() { + + } + + override fun onResume() { + super.onResume() + //注册加速度传感器监听 + val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) + sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL) + + //注册磁场传感器监听 + val magnetic = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) + sensorManager.registerListener(this, magnetic, SensorManager.SENSOR_DELAY_NORMAL) + } + + override fun onPause() { + super.onPause() + sensorManager.unregisterListener(this) + } + + override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) { + //精度发生变化时触发 + } + + override fun onSensorChanged(event: SensorEvent?) { + //值发生变化时触发 + val type = event?.sensor?.type + + if (type == Sensor.TYPE_ACCELEROMETER) { + gravity = event.values + } else if (type == Sensor.TYPE_MAGNETIC_FIELD) { + geomagnetic = event.values + } + + if (gravity == null || geomagnetic == null) { + return + } + + if (SensorManager.getRotationMatrix(rotationMatrix, null, gravity, geomagnetic)) { + SensorManager.getOrientation(rotationMatrix, valueArray) + + val degree = ((360f + valueArray[0] * 180f / Math.PI) % 360).toInt() + //更新罗盘角度 + binding.radarScanView.setDegreeValue(degree) + } + } + + override fun onDestroy() { + super.onDestroy() + soundPool.autoPause() + locationKit.stopLocation() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerAuditActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerAuditActivity.kt deleted file mode 100644 index 6a4aa81..0000000 --- a/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerAuditActivity.kt +++ /dev/null @@ -1,191 +0,0 @@ -package com.casic.common.detector.gd.view - -import android.hardware.Sensor -import android.hardware.SensorEvent -import android.hardware.SensorEventListener -import android.hardware.SensorManager -import android.media.AudioAttributes -import android.media.SoundPool -import android.os.Bundle -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.BaseApplication -import com.casic.common.detector.gd.callback.OnGetLocationListener -import com.casic.common.detector.gd.databinding.ActivitySearchMarkerAuditBinding -import com.casic.common.detector.gd.utils.LocaleConstant -import com.casic.common.detector.gd.utils.LocationKit -import com.casic.common.detector.gd.widgets.MarkerDetailDialog -import com.casic.common.detector.gd.widgets.NewMarkerDetailDialog -import com.casic.common.detector.gd.widgets.RadarScanView -import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.show -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 SearchMarkerAuditActivity : KotlinBaseActivity(), - SensorEventListener { - - private val kTag = "SearchMarkerActivity" - private val context = this - private val locationKit by lazy { LocationKit(this) } - private val sensorManager by lazy { getSystemService(SENSOR_SERVICE) as SensorManager } - private val markerBeanDao by lazy { BaseApplication.get().dataBase.markerBeanDao() } - private val attr = AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ALARM) - .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build() - private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build() - private val rotationMatrix = FloatArray(9)//旋转矩阵缓存 - private val valueArray = FloatArray(3)//方位角数值 - private var nearestMarkerId = ""//探测不到标识器的时候计算出来的最近的标识器ID - private var gravity: FloatArray? = null - private var geomagnetic: FloatArray? = null - private lateinit var searchSignalEnergyTimer: Timer - - override fun initOnCreate(savedInstanceState: Bundle?) { - val fastSoundResourceId = soundPool.load(this, R.raw.ring2, 1) - - //点位渲染,每次定位都计算当前位置与符合条件的点距离 - locationKit.getCurrentLocation(false, object : OnGetLocationListener { - override fun onSuccess(location: AMapLocation) { - renderDataPoint(location) - } - - override fun onError() { - "当前位置信号差,无法获取定位".show(context) - } - }) - - searchSignalEnergyTimer = Timer() - searchSignalEnergyTimer.schedule(object : TimerTask() { - override fun run() { - soundPool.play(fastSoundResourceId, 1f, 1f, 0, 0, 1f) - } - }, 0, 100) - } - - override fun initEvent() { - binding.markerInfoButton.setOnClickListener { - //查库 - val result = markerBeanDao.queryMarkerById(nearestMarkerId) - if (result.isNotEmpty()) { - MarkerDetailDialog(this).setMarker(result.first()).show() - } else { - NewMarkerDetailDialog(this, nearestMarkerId) - } - } - } - - /** - * 计算并渲染数据点。点太多采用协程计算,不然会有点卡顿。默认2s计算一次 - * @param location 定位点(RTK获取) - * */ - private fun renderDataPoint(location: AMapLocation) { - val longitude = location.longitude - val latitude = location.latitude - lifecycleScope.launch(Dispatchers.IO) { - val dataPoints = ArrayList() - markerBeanDao.loadAll().forEach { - val distance = AMapUtils.calculateLineDistance( - LatLng(it.lat.toDouble(), it.lng.toDouble()), LatLng(latitude, longitude) - ) - val formatDistance = "%.2f".format(distance).toFloat() - val angle = atan2( - (it.lat.toDouble() - latitude), (it.lng.toDouble() - longitude) - ) + Math.PI - val formatAngle = "%.2f".format(angle).toDouble() - - dataPoints.add( - RadarScanView.DataPoint(it.markerId, formatAngle, formatDistance) - ) - } - withContext(Dispatchers.Main) { - binding.radarScanView.renderPointData( - dataPoints, - onGetNearestPoint = { point -> - if (point == null) { - binding.distanceValueView.text = "大于5.5m" - binding.distancePgBar.progress = 100 - } else { - nearestMarkerId = point.markerId - binding.distanceValueView.text = "${point.distance}m" - val progress = if (point.distance > LocaleConstant.MAX_DISTANCE) { - 100 - } else { - (point.distance / LocaleConstant.MAX_DISTANCE) * 100 - } - binding.distancePgBar.progress = progress.toInt() - } - } - ) - } - } - } - - override fun initViewBinding(): ActivitySearchMarkerAuditBinding { - return ActivitySearchMarkerAuditBinding.inflate(layoutInflater) - } - - override fun observeRequestState() { - - } - - override fun setupTopBarLayout() { - - } - - override fun onResume() { - super.onResume() - //注册加速度传感器监听 - val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) - sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL) - - //注册磁场传感器监听 - val magnetic = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) - sensorManager.registerListener(this, magnetic, SensorManager.SENSOR_DELAY_NORMAL) - } - - override fun onPause() { - super.onPause() - sensorManager.unregisterListener(this) - } - - override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) { - //精度发生变化时触发 - } - - override fun onSensorChanged(event: SensorEvent?) { - //值发生变化时触发 - val type = event?.sensor?.type - - if (type == Sensor.TYPE_ACCELEROMETER) { - gravity = event.values - } else if (type == Sensor.TYPE_MAGNETIC_FIELD) { - geomagnetic = event.values - } - - if (gravity == null || geomagnetic == null) { - return - } - - if (SensorManager.getRotationMatrix(rotationMatrix, null, gravity, geomagnetic)) { - SensorManager.getOrientation(rotationMatrix, valueArray) - - val degree = ((360f + valueArray[0] * 180f / Math.PI) % 360).toInt() - //更新罗盘角度 - binding.radarScanView.setDegreeValue(degree) - } - } - - override fun onDestroy() { - super.onDestroy() - searchSignalEnergyTimer.cancel() - soundPool.release() - locationKit.stopLocation() - } -} \ No newline at end of file