diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt b/app/src/main/java/com/casic/electric/detector/extensions/Context.kt deleted file mode 100644 index fcf36a7..0000000 --- a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.casic.electric.detector.extensions - -import android.content.Context -import android.view.ViewGroup -import com.pengxh.kt.lite.extensions.getStatusBarHeight - -/** - * 设置沉浸式状态栏,兼容Android 11+ - * */ -fun Context.initLayoutImmersionBar(rootView: ViewGroup) { - rootView.setPadding(0, this.getStatusBarHeight(), 0, 0) - rootView.requestLayout() -} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt b/app/src/main/java/com/casic/electric/detector/extensions/Context.kt deleted file mode 100644 index fcf36a7..0000000 --- a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.casic.electric.detector.extensions - -import android.content.Context -import android.view.ViewGroup -import com.pengxh.kt.lite.extensions.getStatusBarHeight - -/** - * 设置沉浸式状态栏,兼容Android 11+ - * */ -fun Context.initLayoutImmersionBar(rootView: ViewGroup) { - rootView.setPadding(0, this.getStatusBarHeight(), 0, 0) - rootView.requestLayout() -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt index 6e08b27..e98408a 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt @@ -13,12 +13,4 @@ paint.color = color canvas.drawArc(rectF, 0f, 360f, true, paint) return bitmap -} - -fun Int.appendZero(): String { - return if (this < 10) { - "0$this" - } else { - this.toString() - } } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt b/app/src/main/java/com/casic/electric/detector/extensions/Context.kt deleted file mode 100644 index fcf36a7..0000000 --- a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.casic.electric.detector.extensions - -import android.content.Context -import android.view.ViewGroup -import com.pengxh.kt.lite.extensions.getStatusBarHeight - -/** - * 设置沉浸式状态栏,兼容Android 11+ - * */ -fun Context.initLayoutImmersionBar(rootView: ViewGroup) { - rootView.setPadding(0, this.getStatusBarHeight(), 0, 0) - rootView.requestLayout() -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt index 6e08b27..e98408a 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt @@ -13,12 +13,4 @@ paint.color = color canvas.drawArc(rectF, 0f, 360f, true, paint) return bitmap -} - -fun Int.appendZero(): String { - return if (this < 10) { - "0$this" - } else { - this.toString() - } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/String.kt b/app/src/main/java/com/casic/electric/detector/extensions/String.kt index a0db0eb..838d3ad 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/String.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/String.kt @@ -3,14 +3,11 @@ import android.content.Context import android.widget.TextView import com.casic.electric.detector.callback.OnImageCompressListener -import com.casic.electric.detector.model.ErrorMessageModel import com.casic.electric.detector.utils.FileType import com.casic.electric.detector.utils.LocaleConstant -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken +import com.google.gson.JsonParser import com.pengxh.kt.lite.extensions.createCompressImageDir import com.pengxh.kt.lite.utils.SaveKeyValues -import org.json.JSONObject import top.zibin.luban.Luban import top.zibin.luban.OnCompressListener import java.io.File @@ -18,18 +15,22 @@ /** * String扩展方法 */ -fun String.separateResponseState(): Boolean { +fun String.getResponseState(): Boolean { if (this.isBlank()) { return false } - return JSONObject(this).getBoolean("success") + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("success").asBoolean } -fun String.toErrorMessage(): String { - val errorModel = Gson().fromJson( - this, object : TypeToken() {}.type - ) - return errorModel.message.toString() +fun String.getResponseMessage(): String { + if (this.isBlank()) { + return "" + } + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("message").asString } /** @@ -131,4 +132,9 @@ } else { "6" } +} + +fun String.isNumber(): Boolean { + val regex = Regex("[-+]?\\d+(\\.\\d+)?") + return this.matches(regex) } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt b/app/src/main/java/com/casic/electric/detector/extensions/Context.kt deleted file mode 100644 index fcf36a7..0000000 --- a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.casic.electric.detector.extensions - -import android.content.Context -import android.view.ViewGroup -import com.pengxh.kt.lite.extensions.getStatusBarHeight - -/** - * 设置沉浸式状态栏,兼容Android 11+ - * */ -fun Context.initLayoutImmersionBar(rootView: ViewGroup) { - rootView.setPadding(0, this.getStatusBarHeight(), 0, 0) - rootView.requestLayout() -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt index 6e08b27..e98408a 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt @@ -13,12 +13,4 @@ paint.color = color canvas.drawArc(rectF, 0f, 360f, true, paint) return bitmap -} - -fun Int.appendZero(): String { - return if (this < 10) { - "0$this" - } else { - this.toString() - } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/String.kt b/app/src/main/java/com/casic/electric/detector/extensions/String.kt index a0db0eb..838d3ad 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/String.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/String.kt @@ -3,14 +3,11 @@ import android.content.Context import android.widget.TextView import com.casic.electric.detector.callback.OnImageCompressListener -import com.casic.electric.detector.model.ErrorMessageModel import com.casic.electric.detector.utils.FileType import com.casic.electric.detector.utils.LocaleConstant -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken +import com.google.gson.JsonParser import com.pengxh.kt.lite.extensions.createCompressImageDir import com.pengxh.kt.lite.utils.SaveKeyValues -import org.json.JSONObject import top.zibin.luban.Luban import top.zibin.luban.OnCompressListener import java.io.File @@ -18,18 +15,22 @@ /** * String扩展方法 */ -fun String.separateResponseState(): Boolean { +fun String.getResponseState(): Boolean { if (this.isBlank()) { return false } - return JSONObject(this).getBoolean("success") + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("success").asBoolean } -fun String.toErrorMessage(): String { - val errorModel = Gson().fromJson( - this, object : TypeToken() {}.type - ) - return errorModel.message.toString() +fun String.getResponseMessage(): String { + if (this.isBlank()) { + return "" + } + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("message").asString } /** @@ -131,4 +132,9 @@ } else { "6" } +} + +fun String.isNumber(): Boolean { + val regex = Regex("[-+]?\\d+(\\.\\d+)?") + return this.matches(regex) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt new file mode 100644 index 0000000..8b78a3c --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt @@ -0,0 +1,31 @@ +package com.casic.electric.detector.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import androidx.fragment.app.Fragment +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} + +fun ViewGroup.initImmersionBar(fragment: Fragment, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(fragment) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(fragment.requireContext())) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = fragment.requireContext().getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt b/app/src/main/java/com/casic/electric/detector/extensions/Context.kt deleted file mode 100644 index fcf36a7..0000000 --- a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.casic.electric.detector.extensions - -import android.content.Context -import android.view.ViewGroup -import com.pengxh.kt.lite.extensions.getStatusBarHeight - -/** - * 设置沉浸式状态栏,兼容Android 11+ - * */ -fun Context.initLayoutImmersionBar(rootView: ViewGroup) { - rootView.setPadding(0, this.getStatusBarHeight(), 0, 0) - rootView.requestLayout() -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt index 6e08b27..e98408a 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt @@ -13,12 +13,4 @@ paint.color = color canvas.drawArc(rectF, 0f, 360f, true, paint) return bitmap -} - -fun Int.appendZero(): String { - return if (this < 10) { - "0$this" - } else { - this.toString() - } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/String.kt b/app/src/main/java/com/casic/electric/detector/extensions/String.kt index a0db0eb..838d3ad 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/String.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/String.kt @@ -3,14 +3,11 @@ import android.content.Context import android.widget.TextView import com.casic.electric.detector.callback.OnImageCompressListener -import com.casic.electric.detector.model.ErrorMessageModel import com.casic.electric.detector.utils.FileType import com.casic.electric.detector.utils.LocaleConstant -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken +import com.google.gson.JsonParser import com.pengxh.kt.lite.extensions.createCompressImageDir import com.pengxh.kt.lite.utils.SaveKeyValues -import org.json.JSONObject import top.zibin.luban.Luban import top.zibin.luban.OnCompressListener import java.io.File @@ -18,18 +15,22 @@ /** * String扩展方法 */ -fun String.separateResponseState(): Boolean { +fun String.getResponseState(): Boolean { if (this.isBlank()) { return false } - return JSONObject(this).getBoolean("success") + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("success").asBoolean } -fun String.toErrorMessage(): String { - val errorModel = Gson().fromJson( - this, object : TypeToken() {}.type - ) - return errorModel.message.toString() +fun String.getResponseMessage(): String { + if (this.isBlank()) { + return "" + } + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("message").asString } /** @@ -131,4 +132,9 @@ } else { "6" } +} + +fun String.isNumber(): Boolean { + val regex = Regex("[-+]?\\d+(\\.\\d+)?") + return this.matches(regex) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt new file mode 100644 index 0000000..8b78a3c --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt @@ -0,0 +1,31 @@ +package com.casic.electric.detector.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import androidx.fragment.app.Fragment +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} + +fun ViewGroup.initImmersionBar(fragment: Fragment, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(fragment) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(fragment.requireContext())) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = fragment.requireContext().getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt new file mode 100644 index 0000000..84c9cd9 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt @@ -0,0 +1,3 @@ +package com.casic.electric.detector.model + +data class CalculateResult(val angle: Int, val direction: String, val distance: Int) diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt b/app/src/main/java/com/casic/electric/detector/extensions/Context.kt deleted file mode 100644 index fcf36a7..0000000 --- a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.casic.electric.detector.extensions - -import android.content.Context -import android.view.ViewGroup -import com.pengxh.kt.lite.extensions.getStatusBarHeight - -/** - * 设置沉浸式状态栏,兼容Android 11+ - * */ -fun Context.initLayoutImmersionBar(rootView: ViewGroup) { - rootView.setPadding(0, this.getStatusBarHeight(), 0, 0) - rootView.requestLayout() -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt index 6e08b27..e98408a 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt @@ -13,12 +13,4 @@ paint.color = color canvas.drawArc(rectF, 0f, 360f, true, paint) return bitmap -} - -fun Int.appendZero(): String { - return if (this < 10) { - "0$this" - } else { - this.toString() - } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/String.kt b/app/src/main/java/com/casic/electric/detector/extensions/String.kt index a0db0eb..838d3ad 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/String.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/String.kt @@ -3,14 +3,11 @@ import android.content.Context import android.widget.TextView import com.casic.electric.detector.callback.OnImageCompressListener -import com.casic.electric.detector.model.ErrorMessageModel import com.casic.electric.detector.utils.FileType import com.casic.electric.detector.utils.LocaleConstant -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken +import com.google.gson.JsonParser import com.pengxh.kt.lite.extensions.createCompressImageDir import com.pengxh.kt.lite.utils.SaveKeyValues -import org.json.JSONObject import top.zibin.luban.Luban import top.zibin.luban.OnCompressListener import java.io.File @@ -18,18 +15,22 @@ /** * String扩展方法 */ -fun String.separateResponseState(): Boolean { +fun String.getResponseState(): Boolean { if (this.isBlank()) { return false } - return JSONObject(this).getBoolean("success") + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("success").asBoolean } -fun String.toErrorMessage(): String { - val errorModel = Gson().fromJson( - this, object : TypeToken() {}.type - ) - return errorModel.message.toString() +fun String.getResponseMessage(): String { + if (this.isBlank()) { + return "" + } + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("message").asString } /** @@ -131,4 +132,9 @@ } else { "6" } +} + +fun String.isNumber(): Boolean { + val regex = Regex("[-+]?\\d+(\\.\\d+)?") + return this.matches(regex) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt new file mode 100644 index 0000000..8b78a3c --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt @@ -0,0 +1,31 @@ +package com.casic.electric.detector.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import androidx.fragment.app.Fragment +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} + +fun ViewGroup.initImmersionBar(fragment: Fragment, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(fragment) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(fragment.requireContext())) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = fragment.requireContext().getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt new file mode 100644 index 0000000..84c9cd9 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt @@ -0,0 +1,3 @@ +package com.casic.electric.detector.model + +data class CalculateResult(val angle: Int, val direction: String, val distance: Int) diff --git a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java b/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java deleted file mode 100644 index 1574393..0000000 --- a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.casic.electric.detector.model; - -public class ErrorMessageModel { - private int code; - private String data; - private String exceptionClazz; - private String message; - private boolean isSuccess; - - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public String getExceptionClazz() { - return exceptionClazz; - } - - public void setExceptionClazz(String exceptionClazz) { - this.exceptionClazz = exceptionClazz; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public boolean isSuccess() { - return isSuccess; - } - - public void setSuccess(boolean success) { - isSuccess = success; - } -} diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt b/app/src/main/java/com/casic/electric/detector/extensions/Context.kt deleted file mode 100644 index fcf36a7..0000000 --- a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.casic.electric.detector.extensions - -import android.content.Context -import android.view.ViewGroup -import com.pengxh.kt.lite.extensions.getStatusBarHeight - -/** - * 设置沉浸式状态栏,兼容Android 11+ - * */ -fun Context.initLayoutImmersionBar(rootView: ViewGroup) { - rootView.setPadding(0, this.getStatusBarHeight(), 0, 0) - rootView.requestLayout() -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt index 6e08b27..e98408a 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt @@ -13,12 +13,4 @@ paint.color = color canvas.drawArc(rectF, 0f, 360f, true, paint) return bitmap -} - -fun Int.appendZero(): String { - return if (this < 10) { - "0$this" - } else { - this.toString() - } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/String.kt b/app/src/main/java/com/casic/electric/detector/extensions/String.kt index a0db0eb..838d3ad 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/String.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/String.kt @@ -3,14 +3,11 @@ import android.content.Context import android.widget.TextView import com.casic.electric.detector.callback.OnImageCompressListener -import com.casic.electric.detector.model.ErrorMessageModel import com.casic.electric.detector.utils.FileType import com.casic.electric.detector.utils.LocaleConstant -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken +import com.google.gson.JsonParser import com.pengxh.kt.lite.extensions.createCompressImageDir import com.pengxh.kt.lite.utils.SaveKeyValues -import org.json.JSONObject import top.zibin.luban.Luban import top.zibin.luban.OnCompressListener import java.io.File @@ -18,18 +15,22 @@ /** * String扩展方法 */ -fun String.separateResponseState(): Boolean { +fun String.getResponseState(): Boolean { if (this.isBlank()) { return false } - return JSONObject(this).getBoolean("success") + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("success").asBoolean } -fun String.toErrorMessage(): String { - val errorModel = Gson().fromJson( - this, object : TypeToken() {}.type - ) - return errorModel.message.toString() +fun String.getResponseMessage(): String { + if (this.isBlank()) { + return "" + } + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("message").asString } /** @@ -131,4 +132,9 @@ } else { "6" } +} + +fun String.isNumber(): Boolean { + val regex = Regex("[-+]?\\d+(\\.\\d+)?") + return this.matches(regex) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt new file mode 100644 index 0000000..8b78a3c --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt @@ -0,0 +1,31 @@ +package com.casic.electric.detector.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import androidx.fragment.app.Fragment +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} + +fun ViewGroup.initImmersionBar(fragment: Fragment, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(fragment) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(fragment.requireContext())) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = fragment.requireContext().getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt new file mode 100644 index 0000000..84c9cd9 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt @@ -0,0 +1,3 @@ +package com.casic.electric.detector.model + +data class CalculateResult(val angle: Int, val direction: String, val distance: Int) diff --git a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java b/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java deleted file mode 100644 index 1574393..0000000 --- a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.casic.electric.detector.model; - -public class ErrorMessageModel { - private int code; - private String data; - private String exceptionClazz; - private String message; - private boolean isSuccess; - - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public String getExceptionClazz() { - return exceptionClazz; - } - - public void setExceptionClazz(String exceptionClazz) { - this.exceptionClazz = exceptionClazz; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public boolean isSuccess() { - return isSuccess; - } - - public void setSuccess(boolean success) { - isSuccess = success; - } -} diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt index 950fb91..f590226 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt @@ -90,10 +90,25 @@ /** * 上传工单中标识器信息 + * info中的主键 */ @GET("/ems/rs/task/update-task-mark") suspend fun uploadMarker( - @Query("userName") userId: String, - @Query("taskDetailId") taskId: String, + @Query("taskDetailId") taskId: String ): String + + /** + * 新建自由巡检任务 + * */ + @GET("ems/rs/task/addAppTask") + suspend fun createFreeTask( + @Query("patrollerId") patrollerId: String, + @Query("description") description: String + ): String + + /** + * 上传自由巡检过程中发现的标识器 + * */ + @POST("ems/event/uploadAppMarker.do") + suspend fun uploadTaskMarker(@Body requestBody: RequestBody): String } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt b/app/src/main/java/com/casic/electric/detector/extensions/Context.kt deleted file mode 100644 index fcf36a7..0000000 --- a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.casic.electric.detector.extensions - -import android.content.Context -import android.view.ViewGroup -import com.pengxh.kt.lite.extensions.getStatusBarHeight - -/** - * 设置沉浸式状态栏,兼容Android 11+ - * */ -fun Context.initLayoutImmersionBar(rootView: ViewGroup) { - rootView.setPadding(0, this.getStatusBarHeight(), 0, 0) - rootView.requestLayout() -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt index 6e08b27..e98408a 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt @@ -13,12 +13,4 @@ paint.color = color canvas.drawArc(rectF, 0f, 360f, true, paint) return bitmap -} - -fun Int.appendZero(): String { - return if (this < 10) { - "0$this" - } else { - this.toString() - } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/String.kt b/app/src/main/java/com/casic/electric/detector/extensions/String.kt index a0db0eb..838d3ad 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/String.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/String.kt @@ -3,14 +3,11 @@ import android.content.Context import android.widget.TextView import com.casic.electric.detector.callback.OnImageCompressListener -import com.casic.electric.detector.model.ErrorMessageModel import com.casic.electric.detector.utils.FileType import com.casic.electric.detector.utils.LocaleConstant -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken +import com.google.gson.JsonParser import com.pengxh.kt.lite.extensions.createCompressImageDir import com.pengxh.kt.lite.utils.SaveKeyValues -import org.json.JSONObject import top.zibin.luban.Luban import top.zibin.luban.OnCompressListener import java.io.File @@ -18,18 +15,22 @@ /** * String扩展方法 */ -fun String.separateResponseState(): Boolean { +fun String.getResponseState(): Boolean { if (this.isBlank()) { return false } - return JSONObject(this).getBoolean("success") + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("success").asBoolean } -fun String.toErrorMessage(): String { - val errorModel = Gson().fromJson( - this, object : TypeToken() {}.type - ) - return errorModel.message.toString() +fun String.getResponseMessage(): String { + if (this.isBlank()) { + return "" + } + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("message").asString } /** @@ -131,4 +132,9 @@ } else { "6" } +} + +fun String.isNumber(): Boolean { + val regex = Regex("[-+]?\\d+(\\.\\d+)?") + return this.matches(regex) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt new file mode 100644 index 0000000..8b78a3c --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt @@ -0,0 +1,31 @@ +package com.casic.electric.detector.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import androidx.fragment.app.Fragment +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} + +fun ViewGroup.initImmersionBar(fragment: Fragment, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(fragment) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(fragment.requireContext())) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = fragment.requireContext().getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt new file mode 100644 index 0000000..84c9cd9 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt @@ -0,0 +1,3 @@ +package com.casic.electric.detector.model + +data class CalculateResult(val angle: Int, val direction: String, val distance: Int) diff --git a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java b/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java deleted file mode 100644 index 1574393..0000000 --- a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.casic.electric.detector.model; - -public class ErrorMessageModel { - private int code; - private String data; - private String exceptionClazz; - private String message; - private boolean isSuccess; - - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public String getExceptionClazz() { - return exceptionClazz; - } - - public void setExceptionClazz(String exceptionClazz) { - this.exceptionClazz = exceptionClazz; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public boolean isSuccess() { - return isSuccess; - } - - public void setSuccess(boolean success) { - isSuccess = success; - } -} diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt index 950fb91..f590226 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt @@ -90,10 +90,25 @@ /** * 上传工单中标识器信息 + * info中的主键 */ @GET("/ems/rs/task/update-task-mark") suspend fun uploadMarker( - @Query("userName") userId: String, - @Query("taskDetailId") taskId: String, + @Query("taskDetailId") taskId: String ): String + + /** + * 新建自由巡检任务 + * */ + @GET("ems/rs/task/addAppTask") + suspend fun createFreeTask( + @Query("patrollerId") patrollerId: String, + @Query("description") description: String + ): String + + /** + * 上传自由巡检过程中发现的标识器 + * */ + @POST("ems/event/uploadAppMarker.do") + suspend fun uploadTaskMarker(@Body requestBody: RequestBody): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt index 6834fc5..7836b28 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt @@ -1,5 +1,6 @@ package com.casic.electric.detector.retrofit +import com.casic.electric.detector.extensions.reformat import com.casic.electric.detector.utils.LabelDataClass import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.SmallLabelDataClass @@ -15,43 +16,32 @@ object RetrofitServiceManager { + private fun createApi(): RetrofitService { + val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String + val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String + val httpConfig = "http://${serverIp}:${serverPort}" + return RetrofitFactory.createRetrofit(httpConfig) + } + /** * 登录 */ suspend fun login(account: String, password: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.login(account, password) + return createApi().login(account, password) } /** * 更新版本 * */ suspend fun getApplicationVersion(): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getApplicationVersion() + return createApi().getApplicationVersion() } /** * 获取标识器信息文件 */ suspend fun getMarkerFile(userId: String, companyId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getMarkerFile(userId, companyId) + return createApi().getMarkerFile(userId, companyId) } /** @@ -64,39 +54,21 @@ "application/json;charset=UTF-8".toMediaType() ) - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getLabelPicture(requestBody) + return createApi().getLabelPicture(requestBody) } /** * 获取巡检工单 */ suspend fun getTask(userName: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getTask(userName) + return createApi().getTask(userName) } /** * 提交工单 */ suspend fun uploadTask(userId: String, taskId: String?, state: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadTask(userId, taskId.toString(), state) + return createApi().uploadTask(userId, taskId.toString(), state) } /** @@ -164,27 +136,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installLabel(res, multiParts[0], multiParts[1], null) + createApi().installLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installLabel(res, multiParts[0], null, null) + createApi().installLabel(res, multiParts[0], null, null) } else -> { - api.installLabel(res, null, null, null) + createApi().installLabel(res, null, null, null) } } } @@ -230,27 +196,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], null) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installSmallLabel(res, multiParts[0], null, null) + createApi().installSmallLabel(res, multiParts[0], null, null) } else -> { - api.installSmallLabel(res, null, null, null) + createApi().installSmallLabel(res, null, null, null) } } } @@ -279,27 +239,23 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2]) + createApi().uploadEvent( + taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2] + ) } 2 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) } 1 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) } else -> { - api.uploadEvent(taskIdMap, eventMap, null, null, null) + createApi().uploadEvent(taskIdMap, eventMap, null, null, null) } } } @@ -307,13 +263,27 @@ /** * 上传工单中标识器信息 */ - suspend fun uploadMarker(userName: String, taskDetailId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadMarker(userName, taskDetailId) + suspend fun uploadMarker(taskDetailId: String): String { + return createApi().uploadMarker(taskDetailId) + } + + /** + * 上传工单中标识器信息 + */ + suspend fun createFreeTask(patrollerId: String, description: String): String { + return createApi().createFreeTask(patrollerId, description) + } + + /** + * 上传自由巡检过程中发现的标识器 + */ + suspend fun uploadTaskMarker(taskId: String, models: ArrayList): String { + val param = JsonObject() + param.addProperty("taskId", taskId) + param.addProperty("ids", models.reformat()) + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return createApi().uploadTaskMarker(requestBody) } } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt b/app/src/main/java/com/casic/electric/detector/extensions/Context.kt deleted file mode 100644 index fcf36a7..0000000 --- a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.casic.electric.detector.extensions - -import android.content.Context -import android.view.ViewGroup -import com.pengxh.kt.lite.extensions.getStatusBarHeight - -/** - * 设置沉浸式状态栏,兼容Android 11+ - * */ -fun Context.initLayoutImmersionBar(rootView: ViewGroup) { - rootView.setPadding(0, this.getStatusBarHeight(), 0, 0) - rootView.requestLayout() -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt index 6e08b27..e98408a 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt @@ -13,12 +13,4 @@ paint.color = color canvas.drawArc(rectF, 0f, 360f, true, paint) return bitmap -} - -fun Int.appendZero(): String { - return if (this < 10) { - "0$this" - } else { - this.toString() - } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/String.kt b/app/src/main/java/com/casic/electric/detector/extensions/String.kt index a0db0eb..838d3ad 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/String.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/String.kt @@ -3,14 +3,11 @@ import android.content.Context import android.widget.TextView import com.casic.electric.detector.callback.OnImageCompressListener -import com.casic.electric.detector.model.ErrorMessageModel import com.casic.electric.detector.utils.FileType import com.casic.electric.detector.utils.LocaleConstant -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken +import com.google.gson.JsonParser import com.pengxh.kt.lite.extensions.createCompressImageDir import com.pengxh.kt.lite.utils.SaveKeyValues -import org.json.JSONObject import top.zibin.luban.Luban import top.zibin.luban.OnCompressListener import java.io.File @@ -18,18 +15,22 @@ /** * String扩展方法 */ -fun String.separateResponseState(): Boolean { +fun String.getResponseState(): Boolean { if (this.isBlank()) { return false } - return JSONObject(this).getBoolean("success") + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("success").asBoolean } -fun String.toErrorMessage(): String { - val errorModel = Gson().fromJson( - this, object : TypeToken() {}.type - ) - return errorModel.message.toString() +fun String.getResponseMessage(): String { + if (this.isBlank()) { + return "" + } + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("message").asString } /** @@ -131,4 +132,9 @@ } else { "6" } +} + +fun String.isNumber(): Boolean { + val regex = Regex("[-+]?\\d+(\\.\\d+)?") + return this.matches(regex) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt new file mode 100644 index 0000000..8b78a3c --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt @@ -0,0 +1,31 @@ +package com.casic.electric.detector.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import androidx.fragment.app.Fragment +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} + +fun ViewGroup.initImmersionBar(fragment: Fragment, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(fragment) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(fragment.requireContext())) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = fragment.requireContext().getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt new file mode 100644 index 0000000..84c9cd9 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt @@ -0,0 +1,3 @@ +package com.casic.electric.detector.model + +data class CalculateResult(val angle: Int, val direction: String, val distance: Int) diff --git a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java b/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java deleted file mode 100644 index 1574393..0000000 --- a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.casic.electric.detector.model; - -public class ErrorMessageModel { - private int code; - private String data; - private String exceptionClazz; - private String message; - private boolean isSuccess; - - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public String getExceptionClazz() { - return exceptionClazz; - } - - public void setExceptionClazz(String exceptionClazz) { - this.exceptionClazz = exceptionClazz; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public boolean isSuccess() { - return isSuccess; - } - - public void setSuccess(boolean success) { - isSuccess = success; - } -} diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt index 950fb91..f590226 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt @@ -90,10 +90,25 @@ /** * 上传工单中标识器信息 + * info中的主键 */ @GET("/ems/rs/task/update-task-mark") suspend fun uploadMarker( - @Query("userName") userId: String, - @Query("taskDetailId") taskId: String, + @Query("taskDetailId") taskId: String ): String + + /** + * 新建自由巡检任务 + * */ + @GET("ems/rs/task/addAppTask") + suspend fun createFreeTask( + @Query("patrollerId") patrollerId: String, + @Query("description") description: String + ): String + + /** + * 上传自由巡检过程中发现的标识器 + * */ + @POST("ems/event/uploadAppMarker.do") + suspend fun uploadTaskMarker(@Body requestBody: RequestBody): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt index 6834fc5..7836b28 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt @@ -1,5 +1,6 @@ package com.casic.electric.detector.retrofit +import com.casic.electric.detector.extensions.reformat import com.casic.electric.detector.utils.LabelDataClass import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.SmallLabelDataClass @@ -15,43 +16,32 @@ object RetrofitServiceManager { + private fun createApi(): RetrofitService { + val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String + val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String + val httpConfig = "http://${serverIp}:${serverPort}" + return RetrofitFactory.createRetrofit(httpConfig) + } + /** * 登录 */ suspend fun login(account: String, password: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.login(account, password) + return createApi().login(account, password) } /** * 更新版本 * */ suspend fun getApplicationVersion(): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getApplicationVersion() + return createApi().getApplicationVersion() } /** * 获取标识器信息文件 */ suspend fun getMarkerFile(userId: String, companyId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getMarkerFile(userId, companyId) + return createApi().getMarkerFile(userId, companyId) } /** @@ -64,39 +54,21 @@ "application/json;charset=UTF-8".toMediaType() ) - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getLabelPicture(requestBody) + return createApi().getLabelPicture(requestBody) } /** * 获取巡检工单 */ suspend fun getTask(userName: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getTask(userName) + return createApi().getTask(userName) } /** * 提交工单 */ suspend fun uploadTask(userId: String, taskId: String?, state: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadTask(userId, taskId.toString(), state) + return createApi().uploadTask(userId, taskId.toString(), state) } /** @@ -164,27 +136,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installLabel(res, multiParts[0], multiParts[1], null) + createApi().installLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installLabel(res, multiParts[0], null, null) + createApi().installLabel(res, multiParts[0], null, null) } else -> { - api.installLabel(res, null, null, null) + createApi().installLabel(res, null, null, null) } } } @@ -230,27 +196,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], null) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installSmallLabel(res, multiParts[0], null, null) + createApi().installSmallLabel(res, multiParts[0], null, null) } else -> { - api.installSmallLabel(res, null, null, null) + createApi().installSmallLabel(res, null, null, null) } } } @@ -279,27 +239,23 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2]) + createApi().uploadEvent( + taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2] + ) } 2 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) } 1 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) } else -> { - api.uploadEvent(taskIdMap, eventMap, null, null, null) + createApi().uploadEvent(taskIdMap, eventMap, null, null, null) } } } @@ -307,13 +263,27 @@ /** * 上传工单中标识器信息 */ - suspend fun uploadMarker(userName: String, taskDetailId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadMarker(userName, taskDetailId) + suspend fun uploadMarker(taskDetailId: String): String { + return createApi().uploadMarker(taskDetailId) + } + + /** + * 上传工单中标识器信息 + */ + suspend fun createFreeTask(patrollerId: String, description: String): String { + return createApi().createFreeTask(patrollerId, description) + } + + /** + * 上传自由巡检过程中发现的标识器 + */ + suspend fun uploadTaskMarker(taskId: String, models: ArrayList): String { + val param = JsonObject() + param.addProperty("taskId", taskId) + param.addProperty("ids", models.reformat()) + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return createApi().uploadTaskMarker(requestBody) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java index 4aba809..45d5a2f 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java +++ b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java @@ -1,8 +1,10 @@ package com.casic.electric.detector.utils; -public class GpioManager { +import android.util.Log; +public class GpioManager { + private static final String TAG = "GpioManager"; private static final int MT6761 = 0; private int selected; private final MT6761Gpio mt6761; @@ -38,6 +40,7 @@ * 璁剧疆GPIO杈撳嚭楂� * *********************************************************************/ public void setGpioHigh(String gpio) { + Log.d(TAG, "setGpioHigh: 调高电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioHigh(); @@ -48,6 +51,7 @@ * 璁剧疆GPIO杈撳嚭浣� * *********************************************************************/ public void setGpioLow(String gpio) { + Log.d(TAG, "setGpioLow: 调低电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioLow(); diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt b/app/src/main/java/com/casic/electric/detector/extensions/Context.kt deleted file mode 100644 index fcf36a7..0000000 --- a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.casic.electric.detector.extensions - -import android.content.Context -import android.view.ViewGroup -import com.pengxh.kt.lite.extensions.getStatusBarHeight - -/** - * 设置沉浸式状态栏,兼容Android 11+ - * */ -fun Context.initLayoutImmersionBar(rootView: ViewGroup) { - rootView.setPadding(0, this.getStatusBarHeight(), 0, 0) - rootView.requestLayout() -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt index 6e08b27..e98408a 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt @@ -13,12 +13,4 @@ paint.color = color canvas.drawArc(rectF, 0f, 360f, true, paint) return bitmap -} - -fun Int.appendZero(): String { - return if (this < 10) { - "0$this" - } else { - this.toString() - } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/String.kt b/app/src/main/java/com/casic/electric/detector/extensions/String.kt index a0db0eb..838d3ad 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/String.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/String.kt @@ -3,14 +3,11 @@ import android.content.Context import android.widget.TextView import com.casic.electric.detector.callback.OnImageCompressListener -import com.casic.electric.detector.model.ErrorMessageModel import com.casic.electric.detector.utils.FileType import com.casic.electric.detector.utils.LocaleConstant -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken +import com.google.gson.JsonParser import com.pengxh.kt.lite.extensions.createCompressImageDir import com.pengxh.kt.lite.utils.SaveKeyValues -import org.json.JSONObject import top.zibin.luban.Luban import top.zibin.luban.OnCompressListener import java.io.File @@ -18,18 +15,22 @@ /** * String扩展方法 */ -fun String.separateResponseState(): Boolean { +fun String.getResponseState(): Boolean { if (this.isBlank()) { return false } - return JSONObject(this).getBoolean("success") + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("success").asBoolean } -fun String.toErrorMessage(): String { - val errorModel = Gson().fromJson( - this, object : TypeToken() {}.type - ) - return errorModel.message.toString() +fun String.getResponseMessage(): String { + if (this.isBlank()) { + return "" + } + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("message").asString } /** @@ -131,4 +132,9 @@ } else { "6" } +} + +fun String.isNumber(): Boolean { + val regex = Regex("[-+]?\\d+(\\.\\d+)?") + return this.matches(regex) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt new file mode 100644 index 0000000..8b78a3c --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt @@ -0,0 +1,31 @@ +package com.casic.electric.detector.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import androidx.fragment.app.Fragment +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} + +fun ViewGroup.initImmersionBar(fragment: Fragment, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(fragment) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(fragment.requireContext())) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = fragment.requireContext().getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt new file mode 100644 index 0000000..84c9cd9 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt @@ -0,0 +1,3 @@ +package com.casic.electric.detector.model + +data class CalculateResult(val angle: Int, val direction: String, val distance: Int) diff --git a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java b/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java deleted file mode 100644 index 1574393..0000000 --- a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.casic.electric.detector.model; - -public class ErrorMessageModel { - private int code; - private String data; - private String exceptionClazz; - private String message; - private boolean isSuccess; - - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public String getExceptionClazz() { - return exceptionClazz; - } - - public void setExceptionClazz(String exceptionClazz) { - this.exceptionClazz = exceptionClazz; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public boolean isSuccess() { - return isSuccess; - } - - public void setSuccess(boolean success) { - isSuccess = success; - } -} diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt index 950fb91..f590226 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt @@ -90,10 +90,25 @@ /** * 上传工单中标识器信息 + * info中的主键 */ @GET("/ems/rs/task/update-task-mark") suspend fun uploadMarker( - @Query("userName") userId: String, - @Query("taskDetailId") taskId: String, + @Query("taskDetailId") taskId: String ): String + + /** + * 新建自由巡检任务 + * */ + @GET("ems/rs/task/addAppTask") + suspend fun createFreeTask( + @Query("patrollerId") patrollerId: String, + @Query("description") description: String + ): String + + /** + * 上传自由巡检过程中发现的标识器 + * */ + @POST("ems/event/uploadAppMarker.do") + suspend fun uploadTaskMarker(@Body requestBody: RequestBody): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt index 6834fc5..7836b28 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt @@ -1,5 +1,6 @@ package com.casic.electric.detector.retrofit +import com.casic.electric.detector.extensions.reformat import com.casic.electric.detector.utils.LabelDataClass import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.SmallLabelDataClass @@ -15,43 +16,32 @@ object RetrofitServiceManager { + private fun createApi(): RetrofitService { + val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String + val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String + val httpConfig = "http://${serverIp}:${serverPort}" + return RetrofitFactory.createRetrofit(httpConfig) + } + /** * 登录 */ suspend fun login(account: String, password: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.login(account, password) + return createApi().login(account, password) } /** * 更新版本 * */ suspend fun getApplicationVersion(): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getApplicationVersion() + return createApi().getApplicationVersion() } /** * 获取标识器信息文件 */ suspend fun getMarkerFile(userId: String, companyId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getMarkerFile(userId, companyId) + return createApi().getMarkerFile(userId, companyId) } /** @@ -64,39 +54,21 @@ "application/json;charset=UTF-8".toMediaType() ) - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getLabelPicture(requestBody) + return createApi().getLabelPicture(requestBody) } /** * 获取巡检工单 */ suspend fun getTask(userName: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getTask(userName) + return createApi().getTask(userName) } /** * 提交工单 */ suspend fun uploadTask(userId: String, taskId: String?, state: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadTask(userId, taskId.toString(), state) + return createApi().uploadTask(userId, taskId.toString(), state) } /** @@ -164,27 +136,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installLabel(res, multiParts[0], multiParts[1], null) + createApi().installLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installLabel(res, multiParts[0], null, null) + createApi().installLabel(res, multiParts[0], null, null) } else -> { - api.installLabel(res, null, null, null) + createApi().installLabel(res, null, null, null) } } } @@ -230,27 +196,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], null) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installSmallLabel(res, multiParts[0], null, null) + createApi().installSmallLabel(res, multiParts[0], null, null) } else -> { - api.installSmallLabel(res, null, null, null) + createApi().installSmallLabel(res, null, null, null) } } } @@ -279,27 +239,23 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2]) + createApi().uploadEvent( + taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2] + ) } 2 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) } 1 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) } else -> { - api.uploadEvent(taskIdMap, eventMap, null, null, null) + createApi().uploadEvent(taskIdMap, eventMap, null, null, null) } } } @@ -307,13 +263,27 @@ /** * 上传工单中标识器信息 */ - suspend fun uploadMarker(userName: String, taskDetailId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadMarker(userName, taskDetailId) + suspend fun uploadMarker(taskDetailId: String): String { + return createApi().uploadMarker(taskDetailId) + } + + /** + * 上传工单中标识器信息 + */ + suspend fun createFreeTask(patrollerId: String, description: String): String { + return createApi().createFreeTask(patrollerId, description) + } + + /** + * 上传自由巡检过程中发现的标识器 + */ + suspend fun uploadTaskMarker(taskId: String, models: ArrayList): String { + val param = JsonObject() + param.addProperty("taskId", taskId) + param.addProperty("ids", models.reformat()) + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return createApi().uploadTaskMarker(requestBody) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java index 4aba809..45d5a2f 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java +++ b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java @@ -1,8 +1,10 @@ package com.casic.electric.detector.utils; -public class GpioManager { +import android.util.Log; +public class GpioManager { + private static final String TAG = "GpioManager"; private static final int MT6761 = 0; private int selected; private final MT6761Gpio mt6761; @@ -38,6 +40,7 @@ * 璁剧疆GPIO杈撳嚭楂� * *********************************************************************/ public void setGpioHigh(String gpio) { + Log.d(TAG, "setGpioHigh: 调高电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioHigh(); @@ -48,6 +51,7 @@ * 璁剧疆GPIO杈撳嚭浣� * *********************************************************************/ public void setGpioLow(String gpio) { + Log.d(TAG, "setGpioLow: 调低电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioLow(); diff --git a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt deleted file mode 100644 index c589c4b..0000000 --- a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.electric.detector.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt b/app/src/main/java/com/casic/electric/detector/extensions/Context.kt deleted file mode 100644 index fcf36a7..0000000 --- a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.casic.electric.detector.extensions - -import android.content.Context -import android.view.ViewGroup -import com.pengxh.kt.lite.extensions.getStatusBarHeight - -/** - * 设置沉浸式状态栏,兼容Android 11+ - * */ -fun Context.initLayoutImmersionBar(rootView: ViewGroup) { - rootView.setPadding(0, this.getStatusBarHeight(), 0, 0) - rootView.requestLayout() -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt index 6e08b27..e98408a 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt @@ -13,12 +13,4 @@ paint.color = color canvas.drawArc(rectF, 0f, 360f, true, paint) return bitmap -} - -fun Int.appendZero(): String { - return if (this < 10) { - "0$this" - } else { - this.toString() - } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/String.kt b/app/src/main/java/com/casic/electric/detector/extensions/String.kt index a0db0eb..838d3ad 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/String.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/String.kt @@ -3,14 +3,11 @@ import android.content.Context import android.widget.TextView import com.casic.electric.detector.callback.OnImageCompressListener -import com.casic.electric.detector.model.ErrorMessageModel import com.casic.electric.detector.utils.FileType import com.casic.electric.detector.utils.LocaleConstant -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken +import com.google.gson.JsonParser import com.pengxh.kt.lite.extensions.createCompressImageDir import com.pengxh.kt.lite.utils.SaveKeyValues -import org.json.JSONObject import top.zibin.luban.Luban import top.zibin.luban.OnCompressListener import java.io.File @@ -18,18 +15,22 @@ /** * String扩展方法 */ -fun String.separateResponseState(): Boolean { +fun String.getResponseState(): Boolean { if (this.isBlank()) { return false } - return JSONObject(this).getBoolean("success") + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("success").asBoolean } -fun String.toErrorMessage(): String { - val errorModel = Gson().fromJson( - this, object : TypeToken() {}.type - ) - return errorModel.message.toString() +fun String.getResponseMessage(): String { + if (this.isBlank()) { + return "" + } + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("message").asString } /** @@ -131,4 +132,9 @@ } else { "6" } +} + +fun String.isNumber(): Boolean { + val regex = Regex("[-+]?\\d+(\\.\\d+)?") + return this.matches(regex) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt new file mode 100644 index 0000000..8b78a3c --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt @@ -0,0 +1,31 @@ +package com.casic.electric.detector.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import androidx.fragment.app.Fragment +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} + +fun ViewGroup.initImmersionBar(fragment: Fragment, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(fragment) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(fragment.requireContext())) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = fragment.requireContext().getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt new file mode 100644 index 0000000..84c9cd9 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt @@ -0,0 +1,3 @@ +package com.casic.electric.detector.model + +data class CalculateResult(val angle: Int, val direction: String, val distance: Int) diff --git a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java b/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java deleted file mode 100644 index 1574393..0000000 --- a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.casic.electric.detector.model; - -public class ErrorMessageModel { - private int code; - private String data; - private String exceptionClazz; - private String message; - private boolean isSuccess; - - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public String getExceptionClazz() { - return exceptionClazz; - } - - public void setExceptionClazz(String exceptionClazz) { - this.exceptionClazz = exceptionClazz; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public boolean isSuccess() { - return isSuccess; - } - - public void setSuccess(boolean success) { - isSuccess = success; - } -} diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt index 950fb91..f590226 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt @@ -90,10 +90,25 @@ /** * 上传工单中标识器信息 + * info中的主键 */ @GET("/ems/rs/task/update-task-mark") suspend fun uploadMarker( - @Query("userName") userId: String, - @Query("taskDetailId") taskId: String, + @Query("taskDetailId") taskId: String ): String + + /** + * 新建自由巡检任务 + * */ + @GET("ems/rs/task/addAppTask") + suspend fun createFreeTask( + @Query("patrollerId") patrollerId: String, + @Query("description") description: String + ): String + + /** + * 上传自由巡检过程中发现的标识器 + * */ + @POST("ems/event/uploadAppMarker.do") + suspend fun uploadTaskMarker(@Body requestBody: RequestBody): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt index 6834fc5..7836b28 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt @@ -1,5 +1,6 @@ package com.casic.electric.detector.retrofit +import com.casic.electric.detector.extensions.reformat import com.casic.electric.detector.utils.LabelDataClass import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.SmallLabelDataClass @@ -15,43 +16,32 @@ object RetrofitServiceManager { + private fun createApi(): RetrofitService { + val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String + val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String + val httpConfig = "http://${serverIp}:${serverPort}" + return RetrofitFactory.createRetrofit(httpConfig) + } + /** * 登录 */ suspend fun login(account: String, password: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.login(account, password) + return createApi().login(account, password) } /** * 更新版本 * */ suspend fun getApplicationVersion(): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getApplicationVersion() + return createApi().getApplicationVersion() } /** * 获取标识器信息文件 */ suspend fun getMarkerFile(userId: String, companyId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getMarkerFile(userId, companyId) + return createApi().getMarkerFile(userId, companyId) } /** @@ -64,39 +54,21 @@ "application/json;charset=UTF-8".toMediaType() ) - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getLabelPicture(requestBody) + return createApi().getLabelPicture(requestBody) } /** * 获取巡检工单 */ suspend fun getTask(userName: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getTask(userName) + return createApi().getTask(userName) } /** * 提交工单 */ suspend fun uploadTask(userId: String, taskId: String?, state: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadTask(userId, taskId.toString(), state) + return createApi().uploadTask(userId, taskId.toString(), state) } /** @@ -164,27 +136,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installLabel(res, multiParts[0], multiParts[1], null) + createApi().installLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installLabel(res, multiParts[0], null, null) + createApi().installLabel(res, multiParts[0], null, null) } else -> { - api.installLabel(res, null, null, null) + createApi().installLabel(res, null, null, null) } } } @@ -230,27 +196,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], null) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installSmallLabel(res, multiParts[0], null, null) + createApi().installSmallLabel(res, multiParts[0], null, null) } else -> { - api.installSmallLabel(res, null, null, null) + createApi().installSmallLabel(res, null, null, null) } } } @@ -279,27 +239,23 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2]) + createApi().uploadEvent( + taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2] + ) } 2 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) } 1 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) } else -> { - api.uploadEvent(taskIdMap, eventMap, null, null, null) + createApi().uploadEvent(taskIdMap, eventMap, null, null, null) } } } @@ -307,13 +263,27 @@ /** * 上传工单中标识器信息 */ - suspend fun uploadMarker(userName: String, taskDetailId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadMarker(userName, taskDetailId) + suspend fun uploadMarker(taskDetailId: String): String { + return createApi().uploadMarker(taskDetailId) + } + + /** + * 上传工单中标识器信息 + */ + suspend fun createFreeTask(patrollerId: String, description: String): String { + return createApi().createFreeTask(patrollerId, description) + } + + /** + * 上传自由巡检过程中发现的标识器 + */ + suspend fun uploadTaskMarker(taskId: String, models: ArrayList): String { + val param = JsonObject() + param.addProperty("taskId", taskId) + param.addProperty("ids", models.reformat()) + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return createApi().uploadTaskMarker(requestBody) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java index 4aba809..45d5a2f 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java +++ b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java @@ -1,8 +1,10 @@ package com.casic.electric.detector.utils; -public class GpioManager { +import android.util.Log; +public class GpioManager { + private static final String TAG = "GpioManager"; private static final int MT6761 = 0; private int selected; private final MT6761Gpio mt6761; @@ -38,6 +40,7 @@ * 璁剧疆GPIO杈撳嚭楂� * *********************************************************************/ public void setGpioHigh(String gpio) { + Log.d(TAG, "setGpioHigh: 调高电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioHigh(); @@ -48,6 +51,7 @@ * 璁剧疆GPIO杈撳嚭浣� * *********************************************************************/ public void setGpioLow(String gpio) { + Log.d(TAG, "setGpioLow: 调低电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioLow(); diff --git a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt deleted file mode 100644 index c589c4b..0000000 --- a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.electric.detector.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt index 4de12f2..9356f9a 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt @@ -13,7 +13,7 @@ ) const val PERMISSIONS_CODE = 999 - const val RADIUS_SIZE = 100f //相距多少米才聚合,单位:米 + const val RADIUS_SIZE = 100 //相距多少米才聚合,单位:米 const val AUTO_SAVE = "AUTO_SAVE" const val USER_ACCOUNT = "USER_ACCOUNT" @@ -28,10 +28,21 @@ const val APP_AUTHORITY = "com.casic.electric.detector.fileprovider" val POPUP_TITLES = arrayOf("更新数据", "下载工单", "关于软件", "事件上报", "标识器补全") - var CONDITION_ARRAY = arrayOf("种类", "编号", "名称", "所属区域", "所属道路", "运检单位", "责任人", "建设时间", "标识器ID") + var CONDITION_ARRAY = arrayOf( + "种类", + "编号", + "名称", + "所属区域", + "所属道路", + "运检单位", + "责任人", + "建设时间", + "标识器ID" + ) var CONTENT_ARRAY = arrayOf("电缆井", "电缆通道", "配电房", "开关站", "台区", "杆塔") var OBJECT_MODE_ARRAY = arrayOf("直线井", "转弯井", "丁字井", "十字井", "其他") - var WELL_COVER_MATERIAL_ARRAY_1 = arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") + var WELL_COVER_MATERIAL_ARRAY_1 = + arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") var WELL_COVER_MATERIAL_ARRAY_2 = arrayOf("水泥杆", "钢管杆", "铁塔", "其他") var CABINET_TYPE_ARRAY = arrayOf("无", "SM6", "SAFE", "RM6", "XGN15", "固体柜") var PIPE_MATERIAL_ARRAY = arrayOf("无", "PVC管", "波纹管", "镀锌钢管") @@ -42,7 +53,16 @@ var CROSS_PIPE_STATE_ARRAY = booleanArrayOf(false, false, false, false, false, false, false) var POINT_TYPE_ARRAY = arrayOf("管线", "管线附属物", "管线特征管点", "交叉穿越点") - var SPINNER_ARRAY = arrayOf("标识器ID", "所属区域", "所属线路", "所属道路", "权属单位", "安装部门", "安装时间", "备注") + var SPINNER_ARRAY = arrayOf( + "标识器ID", + "所属区域", + "所属线路", + "所属道路", + "权属单位", + "安装部门", + "安装时间", + "备注" + ) var DOWN_PIPE_TYPE_ARRAY = arrayOf("热力", "燃气", "供水", "电力", "通信") var BURY_METHOD_ARRAY = arrayOf("直埋", "圆管", "管块", "管沟", "架空") var COLOR_ARRAY = arrayOf("蓝色", "橙色", "红色", "黑色", "紫色", "黄色", "绿色") diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt b/app/src/main/java/com/casic/electric/detector/extensions/Context.kt deleted file mode 100644 index fcf36a7..0000000 --- a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.casic.electric.detector.extensions - -import android.content.Context -import android.view.ViewGroup -import com.pengxh.kt.lite.extensions.getStatusBarHeight - -/** - * 设置沉浸式状态栏,兼容Android 11+ - * */ -fun Context.initLayoutImmersionBar(rootView: ViewGroup) { - rootView.setPadding(0, this.getStatusBarHeight(), 0, 0) - rootView.requestLayout() -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt index 6e08b27..e98408a 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt @@ -13,12 +13,4 @@ paint.color = color canvas.drawArc(rectF, 0f, 360f, true, paint) return bitmap -} - -fun Int.appendZero(): String { - return if (this < 10) { - "0$this" - } else { - this.toString() - } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/String.kt b/app/src/main/java/com/casic/electric/detector/extensions/String.kt index a0db0eb..838d3ad 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/String.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/String.kt @@ -3,14 +3,11 @@ import android.content.Context import android.widget.TextView import com.casic.electric.detector.callback.OnImageCompressListener -import com.casic.electric.detector.model.ErrorMessageModel import com.casic.electric.detector.utils.FileType import com.casic.electric.detector.utils.LocaleConstant -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken +import com.google.gson.JsonParser import com.pengxh.kt.lite.extensions.createCompressImageDir import com.pengxh.kt.lite.utils.SaveKeyValues -import org.json.JSONObject import top.zibin.luban.Luban import top.zibin.luban.OnCompressListener import java.io.File @@ -18,18 +15,22 @@ /** * String扩展方法 */ -fun String.separateResponseState(): Boolean { +fun String.getResponseState(): Boolean { if (this.isBlank()) { return false } - return JSONObject(this).getBoolean("success") + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("success").asBoolean } -fun String.toErrorMessage(): String { - val errorModel = Gson().fromJson( - this, object : TypeToken() {}.type - ) - return errorModel.message.toString() +fun String.getResponseMessage(): String { + if (this.isBlank()) { + return "" + } + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("message").asString } /** @@ -131,4 +132,9 @@ } else { "6" } +} + +fun String.isNumber(): Boolean { + val regex = Regex("[-+]?\\d+(\\.\\d+)?") + return this.matches(regex) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt new file mode 100644 index 0000000..8b78a3c --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt @@ -0,0 +1,31 @@ +package com.casic.electric.detector.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import androidx.fragment.app.Fragment +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} + +fun ViewGroup.initImmersionBar(fragment: Fragment, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(fragment) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(fragment.requireContext())) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = fragment.requireContext().getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt new file mode 100644 index 0000000..84c9cd9 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt @@ -0,0 +1,3 @@ +package com.casic.electric.detector.model + +data class CalculateResult(val angle: Int, val direction: String, val distance: Int) diff --git a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java b/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java deleted file mode 100644 index 1574393..0000000 --- a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.casic.electric.detector.model; - -public class ErrorMessageModel { - private int code; - private String data; - private String exceptionClazz; - private String message; - private boolean isSuccess; - - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public String getExceptionClazz() { - return exceptionClazz; - } - - public void setExceptionClazz(String exceptionClazz) { - this.exceptionClazz = exceptionClazz; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public boolean isSuccess() { - return isSuccess; - } - - public void setSuccess(boolean success) { - isSuccess = success; - } -} diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt index 950fb91..f590226 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt @@ -90,10 +90,25 @@ /** * 上传工单中标识器信息 + * info中的主键 */ @GET("/ems/rs/task/update-task-mark") suspend fun uploadMarker( - @Query("userName") userId: String, - @Query("taskDetailId") taskId: String, + @Query("taskDetailId") taskId: String ): String + + /** + * 新建自由巡检任务 + * */ + @GET("ems/rs/task/addAppTask") + suspend fun createFreeTask( + @Query("patrollerId") patrollerId: String, + @Query("description") description: String + ): String + + /** + * 上传自由巡检过程中发现的标识器 + * */ + @POST("ems/event/uploadAppMarker.do") + suspend fun uploadTaskMarker(@Body requestBody: RequestBody): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt index 6834fc5..7836b28 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt @@ -1,5 +1,6 @@ package com.casic.electric.detector.retrofit +import com.casic.electric.detector.extensions.reformat import com.casic.electric.detector.utils.LabelDataClass import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.SmallLabelDataClass @@ -15,43 +16,32 @@ object RetrofitServiceManager { + private fun createApi(): RetrofitService { + val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String + val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String + val httpConfig = "http://${serverIp}:${serverPort}" + return RetrofitFactory.createRetrofit(httpConfig) + } + /** * 登录 */ suspend fun login(account: String, password: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.login(account, password) + return createApi().login(account, password) } /** * 更新版本 * */ suspend fun getApplicationVersion(): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getApplicationVersion() + return createApi().getApplicationVersion() } /** * 获取标识器信息文件 */ suspend fun getMarkerFile(userId: String, companyId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getMarkerFile(userId, companyId) + return createApi().getMarkerFile(userId, companyId) } /** @@ -64,39 +54,21 @@ "application/json;charset=UTF-8".toMediaType() ) - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getLabelPicture(requestBody) + return createApi().getLabelPicture(requestBody) } /** * 获取巡检工单 */ suspend fun getTask(userName: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getTask(userName) + return createApi().getTask(userName) } /** * 提交工单 */ suspend fun uploadTask(userId: String, taskId: String?, state: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadTask(userId, taskId.toString(), state) + return createApi().uploadTask(userId, taskId.toString(), state) } /** @@ -164,27 +136,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installLabel(res, multiParts[0], multiParts[1], null) + createApi().installLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installLabel(res, multiParts[0], null, null) + createApi().installLabel(res, multiParts[0], null, null) } else -> { - api.installLabel(res, null, null, null) + createApi().installLabel(res, null, null, null) } } } @@ -230,27 +196,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], null) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installSmallLabel(res, multiParts[0], null, null) + createApi().installSmallLabel(res, multiParts[0], null, null) } else -> { - api.installSmallLabel(res, null, null, null) + createApi().installSmallLabel(res, null, null, null) } } } @@ -279,27 +239,23 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2]) + createApi().uploadEvent( + taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2] + ) } 2 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) } 1 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) } else -> { - api.uploadEvent(taskIdMap, eventMap, null, null, null) + createApi().uploadEvent(taskIdMap, eventMap, null, null, null) } } } @@ -307,13 +263,27 @@ /** * 上传工单中标识器信息 */ - suspend fun uploadMarker(userName: String, taskDetailId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadMarker(userName, taskDetailId) + suspend fun uploadMarker(taskDetailId: String): String { + return createApi().uploadMarker(taskDetailId) + } + + /** + * 上传工单中标识器信息 + */ + suspend fun createFreeTask(patrollerId: String, description: String): String { + return createApi().createFreeTask(patrollerId, description) + } + + /** + * 上传自由巡检过程中发现的标识器 + */ + suspend fun uploadTaskMarker(taskId: String, models: ArrayList): String { + val param = JsonObject() + param.addProperty("taskId", taskId) + param.addProperty("ids", models.reformat()) + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return createApi().uploadTaskMarker(requestBody) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java index 4aba809..45d5a2f 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java +++ b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java @@ -1,8 +1,10 @@ package com.casic.electric.detector.utils; -public class GpioManager { +import android.util.Log; +public class GpioManager { + private static final String TAG = "GpioManager"; private static final int MT6761 = 0; private int selected; private final MT6761Gpio mt6761; @@ -38,6 +40,7 @@ * 璁剧疆GPIO杈撳嚭楂� * *********************************************************************/ public void setGpioHigh(String gpio) { + Log.d(TAG, "setGpioHigh: 调高电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioHigh(); @@ -48,6 +51,7 @@ * 璁剧疆GPIO杈撳嚭浣� * *********************************************************************/ public void setGpioLow(String gpio) { + Log.d(TAG, "setGpioLow: 调低电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioLow(); diff --git a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt deleted file mode 100644 index c589c4b..0000000 --- a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.electric.detector.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt index 4de12f2..9356f9a 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt @@ -13,7 +13,7 @@ ) const val PERMISSIONS_CODE = 999 - const val RADIUS_SIZE = 100f //相距多少米才聚合,单位:米 + const val RADIUS_SIZE = 100 //相距多少米才聚合,单位:米 const val AUTO_SAVE = "AUTO_SAVE" const val USER_ACCOUNT = "USER_ACCOUNT" @@ -28,10 +28,21 @@ const val APP_AUTHORITY = "com.casic.electric.detector.fileprovider" val POPUP_TITLES = arrayOf("更新数据", "下载工单", "关于软件", "事件上报", "标识器补全") - var CONDITION_ARRAY = arrayOf("种类", "编号", "名称", "所属区域", "所属道路", "运检单位", "责任人", "建设时间", "标识器ID") + var CONDITION_ARRAY = arrayOf( + "种类", + "编号", + "名称", + "所属区域", + "所属道路", + "运检单位", + "责任人", + "建设时间", + "标识器ID" + ) var CONTENT_ARRAY = arrayOf("电缆井", "电缆通道", "配电房", "开关站", "台区", "杆塔") var OBJECT_MODE_ARRAY = arrayOf("直线井", "转弯井", "丁字井", "十字井", "其他") - var WELL_COVER_MATERIAL_ARRAY_1 = arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") + var WELL_COVER_MATERIAL_ARRAY_1 = + arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") var WELL_COVER_MATERIAL_ARRAY_2 = arrayOf("水泥杆", "钢管杆", "铁塔", "其他") var CABINET_TYPE_ARRAY = arrayOf("无", "SM6", "SAFE", "RM6", "XGN15", "固体柜") var PIPE_MATERIAL_ARRAY = arrayOf("无", "PVC管", "波纹管", "镀锌钢管") @@ -42,7 +53,16 @@ var CROSS_PIPE_STATE_ARRAY = booleanArrayOf(false, false, false, false, false, false, false) var POINT_TYPE_ARRAY = arrayOf("管线", "管线附属物", "管线特征管点", "交叉穿越点") - var SPINNER_ARRAY = arrayOf("标识器ID", "所属区域", "所属线路", "所属道路", "权属单位", "安装部门", "安装时间", "备注") + var SPINNER_ARRAY = arrayOf( + "标识器ID", + "所属区域", + "所属线路", + "所属道路", + "权属单位", + "安装部门", + "安装时间", + "备注" + ) var DOWN_PIPE_TYPE_ARRAY = arrayOf("热力", "燃气", "供水", "电力", "通信") var BURY_METHOD_ARRAY = arrayOf("直埋", "圆管", "管块", "管沟", "架空") var COLOR_ARRAY = arrayOf("蓝色", "橙色", "红色", "黑色", "紫色", "黄色", "绿色") diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt index 4f0f2c7..61e55f6 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt @@ -14,14 +14,16 @@ import com.casic.electric.detector.callback.IAddressListener import com.casic.electric.detector.callback.ILocationListener -object LocationHub { - private const val kTag = "LocationHub" +class LocationHub constructor(context: Context) { - fun getCurrentLocation(context: Context, listener: ILocationListener) { - val locationClient = AMapLocationClient(context) + private val kTag = "LocationHub" + private val locationClient by lazy { AMapLocationClient(context) } + private val codeSearch by lazy { GeocodeSearch(context) } + + fun getCurrentLocation(isOnceLocation: Boolean, listener: ILocationListener) { val locationOption = AMapLocationClientOption() locationOption.locationMode = AMapLocationClientOption.AMapLocationMode.Hight_Accuracy - locationOption.isOnceLocation = true + locationOption.isOnceLocation = isOnceLocation locationClient.setLocationOption(locationOption) locationClient.setLocationListener { if (it.errorCode == 0) { @@ -36,9 +38,8 @@ locationClient.startLocation() } - fun antiCodingLocation(context: Context, location: Location, listener: IAddressListener) { + fun antiCodingLocation(location: Location, listener: IAddressListener) { try { - val codeSearch = GeocodeSearch(context) // 第一个参数表示一个LatLonPoint,第二参数表示范围多少米,第三个参数表示是火系坐标系还是GPS原生坐标系 val query = RegeocodeQuery( LatLonPoint(location.latitude, location.longitude), 10f, GeocodeSearch.AMAP @@ -55,4 +56,8 @@ e.printStackTrace() } } + + fun stopLocation() { + locationClient.stopLocation() + } } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt b/app/src/main/java/com/casic/electric/detector/extensions/Context.kt deleted file mode 100644 index fcf36a7..0000000 --- a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.casic.electric.detector.extensions - -import android.content.Context -import android.view.ViewGroup -import com.pengxh.kt.lite.extensions.getStatusBarHeight - -/** - * 设置沉浸式状态栏,兼容Android 11+ - * */ -fun Context.initLayoutImmersionBar(rootView: ViewGroup) { - rootView.setPadding(0, this.getStatusBarHeight(), 0, 0) - rootView.requestLayout() -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt index 6e08b27..e98408a 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt @@ -13,12 +13,4 @@ paint.color = color canvas.drawArc(rectF, 0f, 360f, true, paint) return bitmap -} - -fun Int.appendZero(): String { - return if (this < 10) { - "0$this" - } else { - this.toString() - } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/String.kt b/app/src/main/java/com/casic/electric/detector/extensions/String.kt index a0db0eb..838d3ad 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/String.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/String.kt @@ -3,14 +3,11 @@ import android.content.Context import android.widget.TextView import com.casic.electric.detector.callback.OnImageCompressListener -import com.casic.electric.detector.model.ErrorMessageModel import com.casic.electric.detector.utils.FileType import com.casic.electric.detector.utils.LocaleConstant -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken +import com.google.gson.JsonParser import com.pengxh.kt.lite.extensions.createCompressImageDir import com.pengxh.kt.lite.utils.SaveKeyValues -import org.json.JSONObject import top.zibin.luban.Luban import top.zibin.luban.OnCompressListener import java.io.File @@ -18,18 +15,22 @@ /** * String扩展方法 */ -fun String.separateResponseState(): Boolean { +fun String.getResponseState(): Boolean { if (this.isBlank()) { return false } - return JSONObject(this).getBoolean("success") + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("success").asBoolean } -fun String.toErrorMessage(): String { - val errorModel = Gson().fromJson( - this, object : TypeToken() {}.type - ) - return errorModel.message.toString() +fun String.getResponseMessage(): String { + if (this.isBlank()) { + return "" + } + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("message").asString } /** @@ -131,4 +132,9 @@ } else { "6" } +} + +fun String.isNumber(): Boolean { + val regex = Regex("[-+]?\\d+(\\.\\d+)?") + return this.matches(regex) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt new file mode 100644 index 0000000..8b78a3c --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt @@ -0,0 +1,31 @@ +package com.casic.electric.detector.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import androidx.fragment.app.Fragment +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} + +fun ViewGroup.initImmersionBar(fragment: Fragment, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(fragment) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(fragment.requireContext())) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = fragment.requireContext().getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt new file mode 100644 index 0000000..84c9cd9 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt @@ -0,0 +1,3 @@ +package com.casic.electric.detector.model + +data class CalculateResult(val angle: Int, val direction: String, val distance: Int) diff --git a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java b/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java deleted file mode 100644 index 1574393..0000000 --- a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.casic.electric.detector.model; - -public class ErrorMessageModel { - private int code; - private String data; - private String exceptionClazz; - private String message; - private boolean isSuccess; - - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public String getExceptionClazz() { - return exceptionClazz; - } - - public void setExceptionClazz(String exceptionClazz) { - this.exceptionClazz = exceptionClazz; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public boolean isSuccess() { - return isSuccess; - } - - public void setSuccess(boolean success) { - isSuccess = success; - } -} diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt index 950fb91..f590226 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt @@ -90,10 +90,25 @@ /** * 上传工单中标识器信息 + * info中的主键 */ @GET("/ems/rs/task/update-task-mark") suspend fun uploadMarker( - @Query("userName") userId: String, - @Query("taskDetailId") taskId: String, + @Query("taskDetailId") taskId: String ): String + + /** + * 新建自由巡检任务 + * */ + @GET("ems/rs/task/addAppTask") + suspend fun createFreeTask( + @Query("patrollerId") patrollerId: String, + @Query("description") description: String + ): String + + /** + * 上传自由巡检过程中发现的标识器 + * */ + @POST("ems/event/uploadAppMarker.do") + suspend fun uploadTaskMarker(@Body requestBody: RequestBody): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt index 6834fc5..7836b28 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt @@ -1,5 +1,6 @@ package com.casic.electric.detector.retrofit +import com.casic.electric.detector.extensions.reformat import com.casic.electric.detector.utils.LabelDataClass import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.SmallLabelDataClass @@ -15,43 +16,32 @@ object RetrofitServiceManager { + private fun createApi(): RetrofitService { + val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String + val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String + val httpConfig = "http://${serverIp}:${serverPort}" + return RetrofitFactory.createRetrofit(httpConfig) + } + /** * 登录 */ suspend fun login(account: String, password: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.login(account, password) + return createApi().login(account, password) } /** * 更新版本 * */ suspend fun getApplicationVersion(): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getApplicationVersion() + return createApi().getApplicationVersion() } /** * 获取标识器信息文件 */ suspend fun getMarkerFile(userId: String, companyId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getMarkerFile(userId, companyId) + return createApi().getMarkerFile(userId, companyId) } /** @@ -64,39 +54,21 @@ "application/json;charset=UTF-8".toMediaType() ) - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getLabelPicture(requestBody) + return createApi().getLabelPicture(requestBody) } /** * 获取巡检工单 */ suspend fun getTask(userName: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getTask(userName) + return createApi().getTask(userName) } /** * 提交工单 */ suspend fun uploadTask(userId: String, taskId: String?, state: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadTask(userId, taskId.toString(), state) + return createApi().uploadTask(userId, taskId.toString(), state) } /** @@ -164,27 +136,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installLabel(res, multiParts[0], multiParts[1], null) + createApi().installLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installLabel(res, multiParts[0], null, null) + createApi().installLabel(res, multiParts[0], null, null) } else -> { - api.installLabel(res, null, null, null) + createApi().installLabel(res, null, null, null) } } } @@ -230,27 +196,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], null) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installSmallLabel(res, multiParts[0], null, null) + createApi().installSmallLabel(res, multiParts[0], null, null) } else -> { - api.installSmallLabel(res, null, null, null) + createApi().installSmallLabel(res, null, null, null) } } } @@ -279,27 +239,23 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2]) + createApi().uploadEvent( + taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2] + ) } 2 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) } 1 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) } else -> { - api.uploadEvent(taskIdMap, eventMap, null, null, null) + createApi().uploadEvent(taskIdMap, eventMap, null, null, null) } } } @@ -307,13 +263,27 @@ /** * 上传工单中标识器信息 */ - suspend fun uploadMarker(userName: String, taskDetailId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadMarker(userName, taskDetailId) + suspend fun uploadMarker(taskDetailId: String): String { + return createApi().uploadMarker(taskDetailId) + } + + /** + * 上传工单中标识器信息 + */ + suspend fun createFreeTask(patrollerId: String, description: String): String { + return createApi().createFreeTask(patrollerId, description) + } + + /** + * 上传自由巡检过程中发现的标识器 + */ + suspend fun uploadTaskMarker(taskId: String, models: ArrayList): String { + val param = JsonObject() + param.addProperty("taskId", taskId) + param.addProperty("ids", models.reformat()) + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return createApi().uploadTaskMarker(requestBody) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java index 4aba809..45d5a2f 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java +++ b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java @@ -1,8 +1,10 @@ package com.casic.electric.detector.utils; -public class GpioManager { +import android.util.Log; +public class GpioManager { + private static final String TAG = "GpioManager"; private static final int MT6761 = 0; private int selected; private final MT6761Gpio mt6761; @@ -38,6 +40,7 @@ * 璁剧疆GPIO杈撳嚭楂� * *********************************************************************/ public void setGpioHigh(String gpio) { + Log.d(TAG, "setGpioHigh: 调高电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioHigh(); @@ -48,6 +51,7 @@ * 璁剧疆GPIO杈撳嚭浣� * *********************************************************************/ public void setGpioLow(String gpio) { + Log.d(TAG, "setGpioLow: 调低电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioLow(); diff --git a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt deleted file mode 100644 index c589c4b..0000000 --- a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.electric.detector.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt index 4de12f2..9356f9a 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt @@ -13,7 +13,7 @@ ) const val PERMISSIONS_CODE = 999 - const val RADIUS_SIZE = 100f //相距多少米才聚合,单位:米 + const val RADIUS_SIZE = 100 //相距多少米才聚合,单位:米 const val AUTO_SAVE = "AUTO_SAVE" const val USER_ACCOUNT = "USER_ACCOUNT" @@ -28,10 +28,21 @@ const val APP_AUTHORITY = "com.casic.electric.detector.fileprovider" val POPUP_TITLES = arrayOf("更新数据", "下载工单", "关于软件", "事件上报", "标识器补全") - var CONDITION_ARRAY = arrayOf("种类", "编号", "名称", "所属区域", "所属道路", "运检单位", "责任人", "建设时间", "标识器ID") + var CONDITION_ARRAY = arrayOf( + "种类", + "编号", + "名称", + "所属区域", + "所属道路", + "运检单位", + "责任人", + "建设时间", + "标识器ID" + ) var CONTENT_ARRAY = arrayOf("电缆井", "电缆通道", "配电房", "开关站", "台区", "杆塔") var OBJECT_MODE_ARRAY = arrayOf("直线井", "转弯井", "丁字井", "十字井", "其他") - var WELL_COVER_MATERIAL_ARRAY_1 = arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") + var WELL_COVER_MATERIAL_ARRAY_1 = + arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") var WELL_COVER_MATERIAL_ARRAY_2 = arrayOf("水泥杆", "钢管杆", "铁塔", "其他") var CABINET_TYPE_ARRAY = arrayOf("无", "SM6", "SAFE", "RM6", "XGN15", "固体柜") var PIPE_MATERIAL_ARRAY = arrayOf("无", "PVC管", "波纹管", "镀锌钢管") @@ -42,7 +53,16 @@ var CROSS_PIPE_STATE_ARRAY = booleanArrayOf(false, false, false, false, false, false, false) var POINT_TYPE_ARRAY = arrayOf("管线", "管线附属物", "管线特征管点", "交叉穿越点") - var SPINNER_ARRAY = arrayOf("标识器ID", "所属区域", "所属线路", "所属道路", "权属单位", "安装部门", "安装时间", "备注") + var SPINNER_ARRAY = arrayOf( + "标识器ID", + "所属区域", + "所属线路", + "所属道路", + "权属单位", + "安装部门", + "安装时间", + "备注" + ) var DOWN_PIPE_TYPE_ARRAY = arrayOf("热力", "燃气", "供水", "电力", "通信") var BURY_METHOD_ARRAY = arrayOf("直埋", "圆管", "管块", "管沟", "架空") var COLOR_ARRAY = arrayOf("蓝色", "橙色", "红色", "黑色", "紫色", "黄色", "绿色") diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt index 4f0f2c7..61e55f6 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt @@ -14,14 +14,16 @@ import com.casic.electric.detector.callback.IAddressListener import com.casic.electric.detector.callback.ILocationListener -object LocationHub { - private const val kTag = "LocationHub" +class LocationHub constructor(context: Context) { - fun getCurrentLocation(context: Context, listener: ILocationListener) { - val locationClient = AMapLocationClient(context) + private val kTag = "LocationHub" + private val locationClient by lazy { AMapLocationClient(context) } + private val codeSearch by lazy { GeocodeSearch(context) } + + fun getCurrentLocation(isOnceLocation: Boolean, listener: ILocationListener) { val locationOption = AMapLocationClientOption() locationOption.locationMode = AMapLocationClientOption.AMapLocationMode.Hight_Accuracy - locationOption.isOnceLocation = true + locationOption.isOnceLocation = isOnceLocation locationClient.setLocationOption(locationOption) locationClient.setLocationListener { if (it.errorCode == 0) { @@ -36,9 +38,8 @@ locationClient.startLocation() } - fun antiCodingLocation(context: Context, location: Location, listener: IAddressListener) { + fun antiCodingLocation(location: Location, listener: IAddressListener) { try { - val codeSearch = GeocodeSearch(context) // 第一个参数表示一个LatLonPoint,第二参数表示范围多少米,第三个参数表示是火系坐标系还是GPS原生坐标系 val query = RegeocodeQuery( LatLonPoint(location.latitude, location.longitude), 10f, GeocodeSearch.AMAP @@ -55,4 +56,8 @@ e.printStackTrace() } } + + fun stopLocation() { + locationClient.stopLocation() + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt b/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt index aa1bdeb..e3d3289 100644 --- a/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt @@ -1,7 +1,6 @@ package com.casic.electric.detector.view import android.content.Context -import android.graphics.Color import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -12,10 +11,10 @@ import com.bumptech.glide.Glide import com.casic.electric.detector.R import com.casic.electric.detector.databinding.ActivityBigImageBinding +import com.casic.electric.detector.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class BigImageActivity : KotlinBaseActivity() { @@ -24,20 +23,12 @@ } override fun setupTopBarLayout() { - ImmerseStatusBarUtil.setColor(this, Color.BLACK) + binding.rootView.initImmersionBar(this, false, R.color.black) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - val index: Int = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return @@ -62,6 +53,14 @@ }) } + override fun observeRequestState() { + + } + + override fun initEvent() { + + } + inner class BigImageAdapter( private val context: Context, private val data: ArrayList ) : PagerAdapter() { diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt b/app/src/main/java/com/casic/electric/detector/extensions/Context.kt deleted file mode 100644 index fcf36a7..0000000 --- a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.casic.electric.detector.extensions - -import android.content.Context -import android.view.ViewGroup -import com.pengxh.kt.lite.extensions.getStatusBarHeight - -/** - * 设置沉浸式状态栏,兼容Android 11+ - * */ -fun Context.initLayoutImmersionBar(rootView: ViewGroup) { - rootView.setPadding(0, this.getStatusBarHeight(), 0, 0) - rootView.requestLayout() -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt index 6e08b27..e98408a 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt @@ -13,12 +13,4 @@ paint.color = color canvas.drawArc(rectF, 0f, 360f, true, paint) return bitmap -} - -fun Int.appendZero(): String { - return if (this < 10) { - "0$this" - } else { - this.toString() - } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/String.kt b/app/src/main/java/com/casic/electric/detector/extensions/String.kt index a0db0eb..838d3ad 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/String.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/String.kt @@ -3,14 +3,11 @@ import android.content.Context import android.widget.TextView import com.casic.electric.detector.callback.OnImageCompressListener -import com.casic.electric.detector.model.ErrorMessageModel import com.casic.electric.detector.utils.FileType import com.casic.electric.detector.utils.LocaleConstant -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken +import com.google.gson.JsonParser import com.pengxh.kt.lite.extensions.createCompressImageDir import com.pengxh.kt.lite.utils.SaveKeyValues -import org.json.JSONObject import top.zibin.luban.Luban import top.zibin.luban.OnCompressListener import java.io.File @@ -18,18 +15,22 @@ /** * String扩展方法 */ -fun String.separateResponseState(): Boolean { +fun String.getResponseState(): Boolean { if (this.isBlank()) { return false } - return JSONObject(this).getBoolean("success") + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("success").asBoolean } -fun String.toErrorMessage(): String { - val errorModel = Gson().fromJson( - this, object : TypeToken() {}.type - ) - return errorModel.message.toString() +fun String.getResponseMessage(): String { + if (this.isBlank()) { + return "" + } + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("message").asString } /** @@ -131,4 +132,9 @@ } else { "6" } +} + +fun String.isNumber(): Boolean { + val regex = Regex("[-+]?\\d+(\\.\\d+)?") + return this.matches(regex) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt new file mode 100644 index 0000000..8b78a3c --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt @@ -0,0 +1,31 @@ +package com.casic.electric.detector.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import androidx.fragment.app.Fragment +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} + +fun ViewGroup.initImmersionBar(fragment: Fragment, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(fragment) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(fragment.requireContext())) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = fragment.requireContext().getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt new file mode 100644 index 0000000..84c9cd9 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt @@ -0,0 +1,3 @@ +package com.casic.electric.detector.model + +data class CalculateResult(val angle: Int, val direction: String, val distance: Int) diff --git a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java b/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java deleted file mode 100644 index 1574393..0000000 --- a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.casic.electric.detector.model; - -public class ErrorMessageModel { - private int code; - private String data; - private String exceptionClazz; - private String message; - private boolean isSuccess; - - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public String getExceptionClazz() { - return exceptionClazz; - } - - public void setExceptionClazz(String exceptionClazz) { - this.exceptionClazz = exceptionClazz; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public boolean isSuccess() { - return isSuccess; - } - - public void setSuccess(boolean success) { - isSuccess = success; - } -} diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt index 950fb91..f590226 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt @@ -90,10 +90,25 @@ /** * 上传工单中标识器信息 + * info中的主键 */ @GET("/ems/rs/task/update-task-mark") suspend fun uploadMarker( - @Query("userName") userId: String, - @Query("taskDetailId") taskId: String, + @Query("taskDetailId") taskId: String ): String + + /** + * 新建自由巡检任务 + * */ + @GET("ems/rs/task/addAppTask") + suspend fun createFreeTask( + @Query("patrollerId") patrollerId: String, + @Query("description") description: String + ): String + + /** + * 上传自由巡检过程中发现的标识器 + * */ + @POST("ems/event/uploadAppMarker.do") + suspend fun uploadTaskMarker(@Body requestBody: RequestBody): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt index 6834fc5..7836b28 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt @@ -1,5 +1,6 @@ package com.casic.electric.detector.retrofit +import com.casic.electric.detector.extensions.reformat import com.casic.electric.detector.utils.LabelDataClass import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.SmallLabelDataClass @@ -15,43 +16,32 @@ object RetrofitServiceManager { + private fun createApi(): RetrofitService { + val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String + val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String + val httpConfig = "http://${serverIp}:${serverPort}" + return RetrofitFactory.createRetrofit(httpConfig) + } + /** * 登录 */ suspend fun login(account: String, password: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.login(account, password) + return createApi().login(account, password) } /** * 更新版本 * */ suspend fun getApplicationVersion(): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getApplicationVersion() + return createApi().getApplicationVersion() } /** * 获取标识器信息文件 */ suspend fun getMarkerFile(userId: String, companyId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getMarkerFile(userId, companyId) + return createApi().getMarkerFile(userId, companyId) } /** @@ -64,39 +54,21 @@ "application/json;charset=UTF-8".toMediaType() ) - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getLabelPicture(requestBody) + return createApi().getLabelPicture(requestBody) } /** * 获取巡检工单 */ suspend fun getTask(userName: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getTask(userName) + return createApi().getTask(userName) } /** * 提交工单 */ suspend fun uploadTask(userId: String, taskId: String?, state: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadTask(userId, taskId.toString(), state) + return createApi().uploadTask(userId, taskId.toString(), state) } /** @@ -164,27 +136,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installLabel(res, multiParts[0], multiParts[1], null) + createApi().installLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installLabel(res, multiParts[0], null, null) + createApi().installLabel(res, multiParts[0], null, null) } else -> { - api.installLabel(res, null, null, null) + createApi().installLabel(res, null, null, null) } } } @@ -230,27 +196,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], null) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installSmallLabel(res, multiParts[0], null, null) + createApi().installSmallLabel(res, multiParts[0], null, null) } else -> { - api.installSmallLabel(res, null, null, null) + createApi().installSmallLabel(res, null, null, null) } } } @@ -279,27 +239,23 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2]) + createApi().uploadEvent( + taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2] + ) } 2 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) } 1 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) } else -> { - api.uploadEvent(taskIdMap, eventMap, null, null, null) + createApi().uploadEvent(taskIdMap, eventMap, null, null, null) } } } @@ -307,13 +263,27 @@ /** * 上传工单中标识器信息 */ - suspend fun uploadMarker(userName: String, taskDetailId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadMarker(userName, taskDetailId) + suspend fun uploadMarker(taskDetailId: String): String { + return createApi().uploadMarker(taskDetailId) + } + + /** + * 上传工单中标识器信息 + */ + suspend fun createFreeTask(patrollerId: String, description: String): String { + return createApi().createFreeTask(patrollerId, description) + } + + /** + * 上传自由巡检过程中发现的标识器 + */ + suspend fun uploadTaskMarker(taskId: String, models: ArrayList): String { + val param = JsonObject() + param.addProperty("taskId", taskId) + param.addProperty("ids", models.reformat()) + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return createApi().uploadTaskMarker(requestBody) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java index 4aba809..45d5a2f 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java +++ b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java @@ -1,8 +1,10 @@ package com.casic.electric.detector.utils; -public class GpioManager { +import android.util.Log; +public class GpioManager { + private static final String TAG = "GpioManager"; private static final int MT6761 = 0; private int selected; private final MT6761Gpio mt6761; @@ -38,6 +40,7 @@ * 璁剧疆GPIO杈撳嚭楂� * *********************************************************************/ public void setGpioHigh(String gpio) { + Log.d(TAG, "setGpioHigh: 调高电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioHigh(); @@ -48,6 +51,7 @@ * 璁剧疆GPIO杈撳嚭浣� * *********************************************************************/ public void setGpioLow(String gpio) { + Log.d(TAG, "setGpioLow: 调低电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioLow(); diff --git a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt deleted file mode 100644 index c589c4b..0000000 --- a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.electric.detector.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt index 4de12f2..9356f9a 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt @@ -13,7 +13,7 @@ ) const val PERMISSIONS_CODE = 999 - const val RADIUS_SIZE = 100f //相距多少米才聚合,单位:米 + const val RADIUS_SIZE = 100 //相距多少米才聚合,单位:米 const val AUTO_SAVE = "AUTO_SAVE" const val USER_ACCOUNT = "USER_ACCOUNT" @@ -28,10 +28,21 @@ const val APP_AUTHORITY = "com.casic.electric.detector.fileprovider" val POPUP_TITLES = arrayOf("更新数据", "下载工单", "关于软件", "事件上报", "标识器补全") - var CONDITION_ARRAY = arrayOf("种类", "编号", "名称", "所属区域", "所属道路", "运检单位", "责任人", "建设时间", "标识器ID") + var CONDITION_ARRAY = arrayOf( + "种类", + "编号", + "名称", + "所属区域", + "所属道路", + "运检单位", + "责任人", + "建设时间", + "标识器ID" + ) var CONTENT_ARRAY = arrayOf("电缆井", "电缆通道", "配电房", "开关站", "台区", "杆塔") var OBJECT_MODE_ARRAY = arrayOf("直线井", "转弯井", "丁字井", "十字井", "其他") - var WELL_COVER_MATERIAL_ARRAY_1 = arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") + var WELL_COVER_MATERIAL_ARRAY_1 = + arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") var WELL_COVER_MATERIAL_ARRAY_2 = arrayOf("水泥杆", "钢管杆", "铁塔", "其他") var CABINET_TYPE_ARRAY = arrayOf("无", "SM6", "SAFE", "RM6", "XGN15", "固体柜") var PIPE_MATERIAL_ARRAY = arrayOf("无", "PVC管", "波纹管", "镀锌钢管") @@ -42,7 +53,16 @@ var CROSS_PIPE_STATE_ARRAY = booleanArrayOf(false, false, false, false, false, false, false) var POINT_TYPE_ARRAY = arrayOf("管线", "管线附属物", "管线特征管点", "交叉穿越点") - var SPINNER_ARRAY = arrayOf("标识器ID", "所属区域", "所属线路", "所属道路", "权属单位", "安装部门", "安装时间", "备注") + var SPINNER_ARRAY = arrayOf( + "标识器ID", + "所属区域", + "所属线路", + "所属道路", + "权属单位", + "安装部门", + "安装时间", + "备注" + ) var DOWN_PIPE_TYPE_ARRAY = arrayOf("热力", "燃气", "供水", "电力", "通信") var BURY_METHOD_ARRAY = arrayOf("直埋", "圆管", "管块", "管沟", "架空") var COLOR_ARRAY = arrayOf("蓝色", "橙色", "红色", "黑色", "紫色", "黄色", "绿色") diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt index 4f0f2c7..61e55f6 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt @@ -14,14 +14,16 @@ import com.casic.electric.detector.callback.IAddressListener import com.casic.electric.detector.callback.ILocationListener -object LocationHub { - private const val kTag = "LocationHub" +class LocationHub constructor(context: Context) { - fun getCurrentLocation(context: Context, listener: ILocationListener) { - val locationClient = AMapLocationClient(context) + private val kTag = "LocationHub" + private val locationClient by lazy { AMapLocationClient(context) } + private val codeSearch by lazy { GeocodeSearch(context) } + + fun getCurrentLocation(isOnceLocation: Boolean, listener: ILocationListener) { val locationOption = AMapLocationClientOption() locationOption.locationMode = AMapLocationClientOption.AMapLocationMode.Hight_Accuracy - locationOption.isOnceLocation = true + locationOption.isOnceLocation = isOnceLocation locationClient.setLocationOption(locationOption) locationClient.setLocationListener { if (it.errorCode == 0) { @@ -36,9 +38,8 @@ locationClient.startLocation() } - fun antiCodingLocation(context: Context, location: Location, listener: IAddressListener) { + fun antiCodingLocation(location: Location, listener: IAddressListener) { try { - val codeSearch = GeocodeSearch(context) // 第一个参数表示一个LatLonPoint,第二参数表示范围多少米,第三个参数表示是火系坐标系还是GPS原生坐标系 val query = RegeocodeQuery( LatLonPoint(location.latitude, location.longitude), 10f, GeocodeSearch.AMAP @@ -55,4 +56,8 @@ e.printStackTrace() } } + + fun stopLocation() { + locationClient.stopLocation() + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt b/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt index aa1bdeb..e3d3289 100644 --- a/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt @@ -1,7 +1,6 @@ package com.casic.electric.detector.view import android.content.Context -import android.graphics.Color import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -12,10 +11,10 @@ import com.bumptech.glide.Glide import com.casic.electric.detector.R import com.casic.electric.detector.databinding.ActivityBigImageBinding +import com.casic.electric.detector.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class BigImageActivity : KotlinBaseActivity() { @@ -24,20 +23,12 @@ } override fun setupTopBarLayout() { - ImmerseStatusBarUtil.setColor(this, Color.BLACK) + binding.rootView.initImmersionBar(this, false, R.color.black) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - val index: Int = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return @@ -62,6 +53,14 @@ }) } + override fun observeRequestState() { + + } + + override fun initEvent() { + + } + inner class BigImageAdapter( private val context: Context, private val data: ArrayList ) : PagerAdapter() { diff --git a/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt b/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt index d3a89ca..6510104 100644 --- a/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt @@ -29,15 +29,15 @@ import com.casic.electric.detector.extensions.* import com.casic.electric.detector.utils.* import com.casic.electric.detector.vm.TaskViewModel -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia import com.luck.picture.lib.interfaces.OnResultCallbackListener import com.pengxh.kt.lite.extensions.* +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -53,7 +53,8 @@ private val context: Context = this@InstallLabelActivity private val gpioManager by lazy { GpioManager() } private val calendar by lazy { Calendar.getInstance() } - private val realPaths: ArrayList = ArrayList() //真实图片路径 + private val locationHub by lazy { LocationHub(this) } + private val realPaths = ArrayList() //真实图片路径 private var soundResId = 0 private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var soundPool: SoundPool @@ -67,12 +68,6 @@ override fun setupTopBarLayout() { binding.titleInclude.titleView.text = "安装新标识器" binding.titleInclude.titleView.setTextColor(R.color.themeColor.convertColor(this)) - - ImmersionBar.with(this) - .statusBarDarkFont(true) - .statusBarColor(R.color.mainBackground) - .init() - initLayoutImmersionBar(binding.rootView) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -126,7 +121,7 @@ binding.markerAttrInclude.remarkView3.setText("remarkView3".getDefaultValue()) //初始化图片九宫格 - imageAdapter = EditableImageAdapter(this, 3, 3f) + imageAdapter = EditableImageAdapter(this, 3, 3) binding.cameraInclude.addImageRecyclerView.adapter = imageAdapter taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] @@ -332,7 +327,7 @@ binding.markerAttrInclude.installTimeView.text = System.currentTimeMillis().timestampToCompleteDate() - LocationHub.getCurrentLocation(this, object : ILocationListener { + locationHub.getCurrentLocation(true, object : ILocationListener { override fun onAMapLocationGet(location: AMapLocation?) { if (location != null) { binding.markerAttrInclude.lngView.text = location.longitude.toString() @@ -518,8 +513,8 @@ weakReferenceHandler.postDelayed({ try { // 发送读标识器或搜索信号 - outputStream?.write("2".toByteArray()) - outputStream?.flush() + out.write("2".toByteArray()) + out.flush() } catch (e: IOException) { e.printStackTrace() } @@ -527,7 +522,7 @@ } } - override fun onDataReceived(buffer: ByteArray?, size: Int) { + override fun onDataReceived(buffer: ByteArray) { Log.d(kTag, "onDataReceived => " + buffer.contentToString()) if (buffer != null) { val message = weakReferenceHandler.obtainMessage() diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt b/app/src/main/java/com/casic/electric/detector/extensions/Context.kt deleted file mode 100644 index fcf36a7..0000000 --- a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.casic.electric.detector.extensions - -import android.content.Context -import android.view.ViewGroup -import com.pengxh.kt.lite.extensions.getStatusBarHeight - -/** - * 设置沉浸式状态栏,兼容Android 11+ - * */ -fun Context.initLayoutImmersionBar(rootView: ViewGroup) { - rootView.setPadding(0, this.getStatusBarHeight(), 0, 0) - rootView.requestLayout() -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt index 6e08b27..e98408a 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt @@ -13,12 +13,4 @@ paint.color = color canvas.drawArc(rectF, 0f, 360f, true, paint) return bitmap -} - -fun Int.appendZero(): String { - return if (this < 10) { - "0$this" - } else { - this.toString() - } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/String.kt b/app/src/main/java/com/casic/electric/detector/extensions/String.kt index a0db0eb..838d3ad 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/String.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/String.kt @@ -3,14 +3,11 @@ import android.content.Context import android.widget.TextView import com.casic.electric.detector.callback.OnImageCompressListener -import com.casic.electric.detector.model.ErrorMessageModel import com.casic.electric.detector.utils.FileType import com.casic.electric.detector.utils.LocaleConstant -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken +import com.google.gson.JsonParser import com.pengxh.kt.lite.extensions.createCompressImageDir import com.pengxh.kt.lite.utils.SaveKeyValues -import org.json.JSONObject import top.zibin.luban.Luban import top.zibin.luban.OnCompressListener import java.io.File @@ -18,18 +15,22 @@ /** * String扩展方法 */ -fun String.separateResponseState(): Boolean { +fun String.getResponseState(): Boolean { if (this.isBlank()) { return false } - return JSONObject(this).getBoolean("success") + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("success").asBoolean } -fun String.toErrorMessage(): String { - val errorModel = Gson().fromJson( - this, object : TypeToken() {}.type - ) - return errorModel.message.toString() +fun String.getResponseMessage(): String { + if (this.isBlank()) { + return "" + } + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("message").asString } /** @@ -131,4 +132,9 @@ } else { "6" } +} + +fun String.isNumber(): Boolean { + val regex = Regex("[-+]?\\d+(\\.\\d+)?") + return this.matches(regex) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt new file mode 100644 index 0000000..8b78a3c --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt @@ -0,0 +1,31 @@ +package com.casic.electric.detector.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import androidx.fragment.app.Fragment +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} + +fun ViewGroup.initImmersionBar(fragment: Fragment, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(fragment) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(fragment.requireContext())) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = fragment.requireContext().getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt new file mode 100644 index 0000000..84c9cd9 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt @@ -0,0 +1,3 @@ +package com.casic.electric.detector.model + +data class CalculateResult(val angle: Int, val direction: String, val distance: Int) diff --git a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java b/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java deleted file mode 100644 index 1574393..0000000 --- a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.casic.electric.detector.model; - -public class ErrorMessageModel { - private int code; - private String data; - private String exceptionClazz; - private String message; - private boolean isSuccess; - - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public String getExceptionClazz() { - return exceptionClazz; - } - - public void setExceptionClazz(String exceptionClazz) { - this.exceptionClazz = exceptionClazz; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public boolean isSuccess() { - return isSuccess; - } - - public void setSuccess(boolean success) { - isSuccess = success; - } -} diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt index 950fb91..f590226 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt @@ -90,10 +90,25 @@ /** * 上传工单中标识器信息 + * info中的主键 */ @GET("/ems/rs/task/update-task-mark") suspend fun uploadMarker( - @Query("userName") userId: String, - @Query("taskDetailId") taskId: String, + @Query("taskDetailId") taskId: String ): String + + /** + * 新建自由巡检任务 + * */ + @GET("ems/rs/task/addAppTask") + suspend fun createFreeTask( + @Query("patrollerId") patrollerId: String, + @Query("description") description: String + ): String + + /** + * 上传自由巡检过程中发现的标识器 + * */ + @POST("ems/event/uploadAppMarker.do") + suspend fun uploadTaskMarker(@Body requestBody: RequestBody): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt index 6834fc5..7836b28 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt @@ -1,5 +1,6 @@ package com.casic.electric.detector.retrofit +import com.casic.electric.detector.extensions.reformat import com.casic.electric.detector.utils.LabelDataClass import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.SmallLabelDataClass @@ -15,43 +16,32 @@ object RetrofitServiceManager { + private fun createApi(): RetrofitService { + val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String + val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String + val httpConfig = "http://${serverIp}:${serverPort}" + return RetrofitFactory.createRetrofit(httpConfig) + } + /** * 登录 */ suspend fun login(account: String, password: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.login(account, password) + return createApi().login(account, password) } /** * 更新版本 * */ suspend fun getApplicationVersion(): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getApplicationVersion() + return createApi().getApplicationVersion() } /** * 获取标识器信息文件 */ suspend fun getMarkerFile(userId: String, companyId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getMarkerFile(userId, companyId) + return createApi().getMarkerFile(userId, companyId) } /** @@ -64,39 +54,21 @@ "application/json;charset=UTF-8".toMediaType() ) - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getLabelPicture(requestBody) + return createApi().getLabelPicture(requestBody) } /** * 获取巡检工单 */ suspend fun getTask(userName: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getTask(userName) + return createApi().getTask(userName) } /** * 提交工单 */ suspend fun uploadTask(userId: String, taskId: String?, state: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadTask(userId, taskId.toString(), state) + return createApi().uploadTask(userId, taskId.toString(), state) } /** @@ -164,27 +136,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installLabel(res, multiParts[0], multiParts[1], null) + createApi().installLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installLabel(res, multiParts[0], null, null) + createApi().installLabel(res, multiParts[0], null, null) } else -> { - api.installLabel(res, null, null, null) + createApi().installLabel(res, null, null, null) } } } @@ -230,27 +196,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], null) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installSmallLabel(res, multiParts[0], null, null) + createApi().installSmallLabel(res, multiParts[0], null, null) } else -> { - api.installSmallLabel(res, null, null, null) + createApi().installSmallLabel(res, null, null, null) } } } @@ -279,27 +239,23 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2]) + createApi().uploadEvent( + taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2] + ) } 2 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) } 1 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) } else -> { - api.uploadEvent(taskIdMap, eventMap, null, null, null) + createApi().uploadEvent(taskIdMap, eventMap, null, null, null) } } } @@ -307,13 +263,27 @@ /** * 上传工单中标识器信息 */ - suspend fun uploadMarker(userName: String, taskDetailId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadMarker(userName, taskDetailId) + suspend fun uploadMarker(taskDetailId: String): String { + return createApi().uploadMarker(taskDetailId) + } + + /** + * 上传工单中标识器信息 + */ + suspend fun createFreeTask(patrollerId: String, description: String): String { + return createApi().createFreeTask(patrollerId, description) + } + + /** + * 上传自由巡检过程中发现的标识器 + */ + suspend fun uploadTaskMarker(taskId: String, models: ArrayList): String { + val param = JsonObject() + param.addProperty("taskId", taskId) + param.addProperty("ids", models.reformat()) + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return createApi().uploadTaskMarker(requestBody) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java index 4aba809..45d5a2f 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java +++ b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java @@ -1,8 +1,10 @@ package com.casic.electric.detector.utils; -public class GpioManager { +import android.util.Log; +public class GpioManager { + private static final String TAG = "GpioManager"; private static final int MT6761 = 0; private int selected; private final MT6761Gpio mt6761; @@ -38,6 +40,7 @@ * 璁剧疆GPIO杈撳嚭楂� * *********************************************************************/ public void setGpioHigh(String gpio) { + Log.d(TAG, "setGpioHigh: 调高电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioHigh(); @@ -48,6 +51,7 @@ * 璁剧疆GPIO杈撳嚭浣� * *********************************************************************/ public void setGpioLow(String gpio) { + Log.d(TAG, "setGpioLow: 调低电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioLow(); diff --git a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt deleted file mode 100644 index c589c4b..0000000 --- a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.electric.detector.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt index 4de12f2..9356f9a 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt @@ -13,7 +13,7 @@ ) const val PERMISSIONS_CODE = 999 - const val RADIUS_SIZE = 100f //相距多少米才聚合,单位:米 + const val RADIUS_SIZE = 100 //相距多少米才聚合,单位:米 const val AUTO_SAVE = "AUTO_SAVE" const val USER_ACCOUNT = "USER_ACCOUNT" @@ -28,10 +28,21 @@ const val APP_AUTHORITY = "com.casic.electric.detector.fileprovider" val POPUP_TITLES = arrayOf("更新数据", "下载工单", "关于软件", "事件上报", "标识器补全") - var CONDITION_ARRAY = arrayOf("种类", "编号", "名称", "所属区域", "所属道路", "运检单位", "责任人", "建设时间", "标识器ID") + var CONDITION_ARRAY = arrayOf( + "种类", + "编号", + "名称", + "所属区域", + "所属道路", + "运检单位", + "责任人", + "建设时间", + "标识器ID" + ) var CONTENT_ARRAY = arrayOf("电缆井", "电缆通道", "配电房", "开关站", "台区", "杆塔") var OBJECT_MODE_ARRAY = arrayOf("直线井", "转弯井", "丁字井", "十字井", "其他") - var WELL_COVER_MATERIAL_ARRAY_1 = arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") + var WELL_COVER_MATERIAL_ARRAY_1 = + arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") var WELL_COVER_MATERIAL_ARRAY_2 = arrayOf("水泥杆", "钢管杆", "铁塔", "其他") var CABINET_TYPE_ARRAY = arrayOf("无", "SM6", "SAFE", "RM6", "XGN15", "固体柜") var PIPE_MATERIAL_ARRAY = arrayOf("无", "PVC管", "波纹管", "镀锌钢管") @@ -42,7 +53,16 @@ var CROSS_PIPE_STATE_ARRAY = booleanArrayOf(false, false, false, false, false, false, false) var POINT_TYPE_ARRAY = arrayOf("管线", "管线附属物", "管线特征管点", "交叉穿越点") - var SPINNER_ARRAY = arrayOf("标识器ID", "所属区域", "所属线路", "所属道路", "权属单位", "安装部门", "安装时间", "备注") + var SPINNER_ARRAY = arrayOf( + "标识器ID", + "所属区域", + "所属线路", + "所属道路", + "权属单位", + "安装部门", + "安装时间", + "备注" + ) var DOWN_PIPE_TYPE_ARRAY = arrayOf("热力", "燃气", "供水", "电力", "通信") var BURY_METHOD_ARRAY = arrayOf("直埋", "圆管", "管块", "管沟", "架空") var COLOR_ARRAY = arrayOf("蓝色", "橙色", "红色", "黑色", "紫色", "黄色", "绿色") diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt index 4f0f2c7..61e55f6 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt @@ -14,14 +14,16 @@ import com.casic.electric.detector.callback.IAddressListener import com.casic.electric.detector.callback.ILocationListener -object LocationHub { - private const val kTag = "LocationHub" +class LocationHub constructor(context: Context) { - fun getCurrentLocation(context: Context, listener: ILocationListener) { - val locationClient = AMapLocationClient(context) + private val kTag = "LocationHub" + private val locationClient by lazy { AMapLocationClient(context) } + private val codeSearch by lazy { GeocodeSearch(context) } + + fun getCurrentLocation(isOnceLocation: Boolean, listener: ILocationListener) { val locationOption = AMapLocationClientOption() locationOption.locationMode = AMapLocationClientOption.AMapLocationMode.Hight_Accuracy - locationOption.isOnceLocation = true + locationOption.isOnceLocation = isOnceLocation locationClient.setLocationOption(locationOption) locationClient.setLocationListener { if (it.errorCode == 0) { @@ -36,9 +38,8 @@ locationClient.startLocation() } - fun antiCodingLocation(context: Context, location: Location, listener: IAddressListener) { + fun antiCodingLocation(location: Location, listener: IAddressListener) { try { - val codeSearch = GeocodeSearch(context) // 第一个参数表示一个LatLonPoint,第二参数表示范围多少米,第三个参数表示是火系坐标系还是GPS原生坐标系 val query = RegeocodeQuery( LatLonPoint(location.latitude, location.longitude), 10f, GeocodeSearch.AMAP @@ -55,4 +56,8 @@ e.printStackTrace() } } + + fun stopLocation() { + locationClient.stopLocation() + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt b/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt index aa1bdeb..e3d3289 100644 --- a/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt @@ -1,7 +1,6 @@ package com.casic.electric.detector.view import android.content.Context -import android.graphics.Color import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -12,10 +11,10 @@ import com.bumptech.glide.Glide import com.casic.electric.detector.R import com.casic.electric.detector.databinding.ActivityBigImageBinding +import com.casic.electric.detector.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class BigImageActivity : KotlinBaseActivity() { @@ -24,20 +23,12 @@ } override fun setupTopBarLayout() { - ImmerseStatusBarUtil.setColor(this, Color.BLACK) + binding.rootView.initImmersionBar(this, false, R.color.black) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - val index: Int = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return @@ -62,6 +53,14 @@ }) } + override fun observeRequestState() { + + } + + override fun initEvent() { + + } + inner class BigImageAdapter( private val context: Context, private val data: ArrayList ) : PagerAdapter() { diff --git a/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt b/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt index d3a89ca..6510104 100644 --- a/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt @@ -29,15 +29,15 @@ import com.casic.electric.detector.extensions.* import com.casic.electric.detector.utils.* import com.casic.electric.detector.vm.TaskViewModel -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia import com.luck.picture.lib.interfaces.OnResultCallbackListener import com.pengxh.kt.lite.extensions.* +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -53,7 +53,8 @@ private val context: Context = this@InstallLabelActivity private val gpioManager by lazy { GpioManager() } private val calendar by lazy { Calendar.getInstance() } - private val realPaths: ArrayList = ArrayList() //真实图片路径 + private val locationHub by lazy { LocationHub(this) } + private val realPaths = ArrayList() //真实图片路径 private var soundResId = 0 private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var soundPool: SoundPool @@ -67,12 +68,6 @@ override fun setupTopBarLayout() { binding.titleInclude.titleView.text = "安装新标识器" binding.titleInclude.titleView.setTextColor(R.color.themeColor.convertColor(this)) - - ImmersionBar.with(this) - .statusBarDarkFont(true) - .statusBarColor(R.color.mainBackground) - .init() - initLayoutImmersionBar(binding.rootView) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -126,7 +121,7 @@ binding.markerAttrInclude.remarkView3.setText("remarkView3".getDefaultValue()) //初始化图片九宫格 - imageAdapter = EditableImageAdapter(this, 3, 3f) + imageAdapter = EditableImageAdapter(this, 3, 3) binding.cameraInclude.addImageRecyclerView.adapter = imageAdapter taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] @@ -332,7 +327,7 @@ binding.markerAttrInclude.installTimeView.text = System.currentTimeMillis().timestampToCompleteDate() - LocationHub.getCurrentLocation(this, object : ILocationListener { + locationHub.getCurrentLocation(true, object : ILocationListener { override fun onAMapLocationGet(location: AMapLocation?) { if (location != null) { binding.markerAttrInclude.lngView.text = location.longitude.toString() @@ -518,8 +513,8 @@ weakReferenceHandler.postDelayed({ try { // 发送读标识器或搜索信号 - outputStream?.write("2".toByteArray()) - outputStream?.flush() + out.write("2".toByteArray()) + out.flush() } catch (e: IOException) { e.printStackTrace() } @@ -527,7 +522,7 @@ } } - override fun onDataReceived(buffer: ByteArray?, size: Int) { + override fun onDataReceived(buffer: ByteArray) { Log.d(kTag, "onDataReceived => " + buffer.contentToString()) if (buffer != null) { val message = weakReferenceHandler.obtainMessage() diff --git a/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt b/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt index 5bc2ac8..286bf4a 100644 --- a/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt @@ -24,7 +24,6 @@ import com.casic.electric.detector.extensions.* import com.casic.electric.detector.utils.* import com.casic.electric.detector.vm.TaskViewModel -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -33,9 +32,10 @@ import com.pengxh.kt.lite.extensions.isNetworkConnected import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -65,12 +65,6 @@ override fun setupTopBarLayout() { binding.titleInclude.titleView.text = "安装新电子标签" binding.titleInclude.titleView.setTextColor(R.color.themeColor.convertColor(this)) - - ImmersionBar.with(this) - .statusBarDarkFont(true) - .statusBarColor(R.color.mainBackground) - .init() - initLayoutImmersionBar(binding.rootView) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -103,7 +97,7 @@ binding.objectAttrInclude.objectRemarkView3.setText("objectRemarkView3".getDefaultValue()) //初始化图片九宫格 - imageAdapter = EditableImageAdapter(this, 3, 3f) + imageAdapter = EditableImageAdapter(this, 3, 3) binding.cameraInclude.addImageRecyclerView.adapter = imageAdapter taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] @@ -308,8 +302,8 @@ weakReferenceHandler.postDelayed({ try { // 发送读标识器或搜索信号 - outputStream?.write("2".toByteArray()) - outputStream?.flush() + out.write("2".toByteArray()) + out.flush() } catch (e: IOException) { e.printStackTrace() } @@ -317,7 +311,7 @@ } } - override fun onDataReceived(buffer: ByteArray?, size: Int) { + override fun onDataReceived(buffer: ByteArray) { if (buffer != null) { val message = weakReferenceHandler.obtainMessage() message.what = 2023081702 diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt b/app/src/main/java/com/casic/electric/detector/extensions/Context.kt deleted file mode 100644 index fcf36a7..0000000 --- a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.casic.electric.detector.extensions - -import android.content.Context -import android.view.ViewGroup -import com.pengxh.kt.lite.extensions.getStatusBarHeight - -/** - * 设置沉浸式状态栏,兼容Android 11+ - * */ -fun Context.initLayoutImmersionBar(rootView: ViewGroup) { - rootView.setPadding(0, this.getStatusBarHeight(), 0, 0) - rootView.requestLayout() -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt index 6e08b27..e98408a 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt @@ -13,12 +13,4 @@ paint.color = color canvas.drawArc(rectF, 0f, 360f, true, paint) return bitmap -} - -fun Int.appendZero(): String { - return if (this < 10) { - "0$this" - } else { - this.toString() - } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/String.kt b/app/src/main/java/com/casic/electric/detector/extensions/String.kt index a0db0eb..838d3ad 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/String.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/String.kt @@ -3,14 +3,11 @@ import android.content.Context import android.widget.TextView import com.casic.electric.detector.callback.OnImageCompressListener -import com.casic.electric.detector.model.ErrorMessageModel import com.casic.electric.detector.utils.FileType import com.casic.electric.detector.utils.LocaleConstant -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken +import com.google.gson.JsonParser import com.pengxh.kt.lite.extensions.createCompressImageDir import com.pengxh.kt.lite.utils.SaveKeyValues -import org.json.JSONObject import top.zibin.luban.Luban import top.zibin.luban.OnCompressListener import java.io.File @@ -18,18 +15,22 @@ /** * String扩展方法 */ -fun String.separateResponseState(): Boolean { +fun String.getResponseState(): Boolean { if (this.isBlank()) { return false } - return JSONObject(this).getBoolean("success") + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("success").asBoolean } -fun String.toErrorMessage(): String { - val errorModel = Gson().fromJson( - this, object : TypeToken() {}.type - ) - return errorModel.message.toString() +fun String.getResponseMessage(): String { + if (this.isBlank()) { + return "" + } + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("message").asString } /** @@ -131,4 +132,9 @@ } else { "6" } +} + +fun String.isNumber(): Boolean { + val regex = Regex("[-+]?\\d+(\\.\\d+)?") + return this.matches(regex) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt new file mode 100644 index 0000000..8b78a3c --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt @@ -0,0 +1,31 @@ +package com.casic.electric.detector.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import androidx.fragment.app.Fragment +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} + +fun ViewGroup.initImmersionBar(fragment: Fragment, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(fragment) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(fragment.requireContext())) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = fragment.requireContext().getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt new file mode 100644 index 0000000..84c9cd9 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt @@ -0,0 +1,3 @@ +package com.casic.electric.detector.model + +data class CalculateResult(val angle: Int, val direction: String, val distance: Int) diff --git a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java b/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java deleted file mode 100644 index 1574393..0000000 --- a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.casic.electric.detector.model; - -public class ErrorMessageModel { - private int code; - private String data; - private String exceptionClazz; - private String message; - private boolean isSuccess; - - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public String getExceptionClazz() { - return exceptionClazz; - } - - public void setExceptionClazz(String exceptionClazz) { - this.exceptionClazz = exceptionClazz; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public boolean isSuccess() { - return isSuccess; - } - - public void setSuccess(boolean success) { - isSuccess = success; - } -} diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt index 950fb91..f590226 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt @@ -90,10 +90,25 @@ /** * 上传工单中标识器信息 + * info中的主键 */ @GET("/ems/rs/task/update-task-mark") suspend fun uploadMarker( - @Query("userName") userId: String, - @Query("taskDetailId") taskId: String, + @Query("taskDetailId") taskId: String ): String + + /** + * 新建自由巡检任务 + * */ + @GET("ems/rs/task/addAppTask") + suspend fun createFreeTask( + @Query("patrollerId") patrollerId: String, + @Query("description") description: String + ): String + + /** + * 上传自由巡检过程中发现的标识器 + * */ + @POST("ems/event/uploadAppMarker.do") + suspend fun uploadTaskMarker(@Body requestBody: RequestBody): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt index 6834fc5..7836b28 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt @@ -1,5 +1,6 @@ package com.casic.electric.detector.retrofit +import com.casic.electric.detector.extensions.reformat import com.casic.electric.detector.utils.LabelDataClass import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.SmallLabelDataClass @@ -15,43 +16,32 @@ object RetrofitServiceManager { + private fun createApi(): RetrofitService { + val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String + val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String + val httpConfig = "http://${serverIp}:${serverPort}" + return RetrofitFactory.createRetrofit(httpConfig) + } + /** * 登录 */ suspend fun login(account: String, password: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.login(account, password) + return createApi().login(account, password) } /** * 更新版本 * */ suspend fun getApplicationVersion(): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getApplicationVersion() + return createApi().getApplicationVersion() } /** * 获取标识器信息文件 */ suspend fun getMarkerFile(userId: String, companyId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getMarkerFile(userId, companyId) + return createApi().getMarkerFile(userId, companyId) } /** @@ -64,39 +54,21 @@ "application/json;charset=UTF-8".toMediaType() ) - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getLabelPicture(requestBody) + return createApi().getLabelPicture(requestBody) } /** * 获取巡检工单 */ suspend fun getTask(userName: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getTask(userName) + return createApi().getTask(userName) } /** * 提交工单 */ suspend fun uploadTask(userId: String, taskId: String?, state: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadTask(userId, taskId.toString(), state) + return createApi().uploadTask(userId, taskId.toString(), state) } /** @@ -164,27 +136,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installLabel(res, multiParts[0], multiParts[1], null) + createApi().installLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installLabel(res, multiParts[0], null, null) + createApi().installLabel(res, multiParts[0], null, null) } else -> { - api.installLabel(res, null, null, null) + createApi().installLabel(res, null, null, null) } } } @@ -230,27 +196,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], null) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installSmallLabel(res, multiParts[0], null, null) + createApi().installSmallLabel(res, multiParts[0], null, null) } else -> { - api.installSmallLabel(res, null, null, null) + createApi().installSmallLabel(res, null, null, null) } } } @@ -279,27 +239,23 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2]) + createApi().uploadEvent( + taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2] + ) } 2 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) } 1 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) } else -> { - api.uploadEvent(taskIdMap, eventMap, null, null, null) + createApi().uploadEvent(taskIdMap, eventMap, null, null, null) } } } @@ -307,13 +263,27 @@ /** * 上传工单中标识器信息 */ - suspend fun uploadMarker(userName: String, taskDetailId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadMarker(userName, taskDetailId) + suspend fun uploadMarker(taskDetailId: String): String { + return createApi().uploadMarker(taskDetailId) + } + + /** + * 上传工单中标识器信息 + */ + suspend fun createFreeTask(patrollerId: String, description: String): String { + return createApi().createFreeTask(patrollerId, description) + } + + /** + * 上传自由巡检过程中发现的标识器 + */ + suspend fun uploadTaskMarker(taskId: String, models: ArrayList): String { + val param = JsonObject() + param.addProperty("taskId", taskId) + param.addProperty("ids", models.reformat()) + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return createApi().uploadTaskMarker(requestBody) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java index 4aba809..45d5a2f 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java +++ b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java @@ -1,8 +1,10 @@ package com.casic.electric.detector.utils; -public class GpioManager { +import android.util.Log; +public class GpioManager { + private static final String TAG = "GpioManager"; private static final int MT6761 = 0; private int selected; private final MT6761Gpio mt6761; @@ -38,6 +40,7 @@ * 璁剧疆GPIO杈撳嚭楂� * *********************************************************************/ public void setGpioHigh(String gpio) { + Log.d(TAG, "setGpioHigh: 调高电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioHigh(); @@ -48,6 +51,7 @@ * 璁剧疆GPIO杈撳嚭浣� * *********************************************************************/ public void setGpioLow(String gpio) { + Log.d(TAG, "setGpioLow: 调低电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioLow(); diff --git a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt deleted file mode 100644 index c589c4b..0000000 --- a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.electric.detector.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt index 4de12f2..9356f9a 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt @@ -13,7 +13,7 @@ ) const val PERMISSIONS_CODE = 999 - const val RADIUS_SIZE = 100f //相距多少米才聚合,单位:米 + const val RADIUS_SIZE = 100 //相距多少米才聚合,单位:米 const val AUTO_SAVE = "AUTO_SAVE" const val USER_ACCOUNT = "USER_ACCOUNT" @@ -28,10 +28,21 @@ const val APP_AUTHORITY = "com.casic.electric.detector.fileprovider" val POPUP_TITLES = arrayOf("更新数据", "下载工单", "关于软件", "事件上报", "标识器补全") - var CONDITION_ARRAY = arrayOf("种类", "编号", "名称", "所属区域", "所属道路", "运检单位", "责任人", "建设时间", "标识器ID") + var CONDITION_ARRAY = arrayOf( + "种类", + "编号", + "名称", + "所属区域", + "所属道路", + "运检单位", + "责任人", + "建设时间", + "标识器ID" + ) var CONTENT_ARRAY = arrayOf("电缆井", "电缆通道", "配电房", "开关站", "台区", "杆塔") var OBJECT_MODE_ARRAY = arrayOf("直线井", "转弯井", "丁字井", "十字井", "其他") - var WELL_COVER_MATERIAL_ARRAY_1 = arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") + var WELL_COVER_MATERIAL_ARRAY_1 = + arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") var WELL_COVER_MATERIAL_ARRAY_2 = arrayOf("水泥杆", "钢管杆", "铁塔", "其他") var CABINET_TYPE_ARRAY = arrayOf("无", "SM6", "SAFE", "RM6", "XGN15", "固体柜") var PIPE_MATERIAL_ARRAY = arrayOf("无", "PVC管", "波纹管", "镀锌钢管") @@ -42,7 +53,16 @@ var CROSS_PIPE_STATE_ARRAY = booleanArrayOf(false, false, false, false, false, false, false) var POINT_TYPE_ARRAY = arrayOf("管线", "管线附属物", "管线特征管点", "交叉穿越点") - var SPINNER_ARRAY = arrayOf("标识器ID", "所属区域", "所属线路", "所属道路", "权属单位", "安装部门", "安装时间", "备注") + var SPINNER_ARRAY = arrayOf( + "标识器ID", + "所属区域", + "所属线路", + "所属道路", + "权属单位", + "安装部门", + "安装时间", + "备注" + ) var DOWN_PIPE_TYPE_ARRAY = arrayOf("热力", "燃气", "供水", "电力", "通信") var BURY_METHOD_ARRAY = arrayOf("直埋", "圆管", "管块", "管沟", "架空") var COLOR_ARRAY = arrayOf("蓝色", "橙色", "红色", "黑色", "紫色", "黄色", "绿色") diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt index 4f0f2c7..61e55f6 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt @@ -14,14 +14,16 @@ import com.casic.electric.detector.callback.IAddressListener import com.casic.electric.detector.callback.ILocationListener -object LocationHub { - private const val kTag = "LocationHub" +class LocationHub constructor(context: Context) { - fun getCurrentLocation(context: Context, listener: ILocationListener) { - val locationClient = AMapLocationClient(context) + private val kTag = "LocationHub" + private val locationClient by lazy { AMapLocationClient(context) } + private val codeSearch by lazy { GeocodeSearch(context) } + + fun getCurrentLocation(isOnceLocation: Boolean, listener: ILocationListener) { val locationOption = AMapLocationClientOption() locationOption.locationMode = AMapLocationClientOption.AMapLocationMode.Hight_Accuracy - locationOption.isOnceLocation = true + locationOption.isOnceLocation = isOnceLocation locationClient.setLocationOption(locationOption) locationClient.setLocationListener { if (it.errorCode == 0) { @@ -36,9 +38,8 @@ locationClient.startLocation() } - fun antiCodingLocation(context: Context, location: Location, listener: IAddressListener) { + fun antiCodingLocation(location: Location, listener: IAddressListener) { try { - val codeSearch = GeocodeSearch(context) // 第一个参数表示一个LatLonPoint,第二参数表示范围多少米,第三个参数表示是火系坐标系还是GPS原生坐标系 val query = RegeocodeQuery( LatLonPoint(location.latitude, location.longitude), 10f, GeocodeSearch.AMAP @@ -55,4 +56,8 @@ e.printStackTrace() } } + + fun stopLocation() { + locationClient.stopLocation() + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt b/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt index aa1bdeb..e3d3289 100644 --- a/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt @@ -1,7 +1,6 @@ package com.casic.electric.detector.view import android.content.Context -import android.graphics.Color import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -12,10 +11,10 @@ import com.bumptech.glide.Glide import com.casic.electric.detector.R import com.casic.electric.detector.databinding.ActivityBigImageBinding +import com.casic.electric.detector.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class BigImageActivity : KotlinBaseActivity() { @@ -24,20 +23,12 @@ } override fun setupTopBarLayout() { - ImmerseStatusBarUtil.setColor(this, Color.BLACK) + binding.rootView.initImmersionBar(this, false, R.color.black) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - val index: Int = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return @@ -62,6 +53,14 @@ }) } + override fun observeRequestState() { + + } + + override fun initEvent() { + + } + inner class BigImageAdapter( private val context: Context, private val data: ArrayList ) : PagerAdapter() { diff --git a/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt b/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt index d3a89ca..6510104 100644 --- a/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt @@ -29,15 +29,15 @@ import com.casic.electric.detector.extensions.* import com.casic.electric.detector.utils.* import com.casic.electric.detector.vm.TaskViewModel -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia import com.luck.picture.lib.interfaces.OnResultCallbackListener import com.pengxh.kt.lite.extensions.* +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -53,7 +53,8 @@ private val context: Context = this@InstallLabelActivity private val gpioManager by lazy { GpioManager() } private val calendar by lazy { Calendar.getInstance() } - private val realPaths: ArrayList = ArrayList() //真实图片路径 + private val locationHub by lazy { LocationHub(this) } + private val realPaths = ArrayList() //真实图片路径 private var soundResId = 0 private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var soundPool: SoundPool @@ -67,12 +68,6 @@ override fun setupTopBarLayout() { binding.titleInclude.titleView.text = "安装新标识器" binding.titleInclude.titleView.setTextColor(R.color.themeColor.convertColor(this)) - - ImmersionBar.with(this) - .statusBarDarkFont(true) - .statusBarColor(R.color.mainBackground) - .init() - initLayoutImmersionBar(binding.rootView) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -126,7 +121,7 @@ binding.markerAttrInclude.remarkView3.setText("remarkView3".getDefaultValue()) //初始化图片九宫格 - imageAdapter = EditableImageAdapter(this, 3, 3f) + imageAdapter = EditableImageAdapter(this, 3, 3) binding.cameraInclude.addImageRecyclerView.adapter = imageAdapter taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] @@ -332,7 +327,7 @@ binding.markerAttrInclude.installTimeView.text = System.currentTimeMillis().timestampToCompleteDate() - LocationHub.getCurrentLocation(this, object : ILocationListener { + locationHub.getCurrentLocation(true, object : ILocationListener { override fun onAMapLocationGet(location: AMapLocation?) { if (location != null) { binding.markerAttrInclude.lngView.text = location.longitude.toString() @@ -518,8 +513,8 @@ weakReferenceHandler.postDelayed({ try { // 发送读标识器或搜索信号 - outputStream?.write("2".toByteArray()) - outputStream?.flush() + out.write("2".toByteArray()) + out.flush() } catch (e: IOException) { e.printStackTrace() } @@ -527,7 +522,7 @@ } } - override fun onDataReceived(buffer: ByteArray?, size: Int) { + override fun onDataReceived(buffer: ByteArray) { Log.d(kTag, "onDataReceived => " + buffer.contentToString()) if (buffer != null) { val message = weakReferenceHandler.obtainMessage() diff --git a/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt b/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt index 5bc2ac8..286bf4a 100644 --- a/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt @@ -24,7 +24,6 @@ import com.casic.electric.detector.extensions.* import com.casic.electric.detector.utils.* import com.casic.electric.detector.vm.TaskViewModel -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -33,9 +32,10 @@ import com.pengxh.kt.lite.extensions.isNetworkConnected import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -65,12 +65,6 @@ override fun setupTopBarLayout() { binding.titleInclude.titleView.text = "安装新电子标签" binding.titleInclude.titleView.setTextColor(R.color.themeColor.convertColor(this)) - - ImmersionBar.with(this) - .statusBarDarkFont(true) - .statusBarColor(R.color.mainBackground) - .init() - initLayoutImmersionBar(binding.rootView) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -103,7 +97,7 @@ binding.objectAttrInclude.objectRemarkView3.setText("objectRemarkView3".getDefaultValue()) //初始化图片九宫格 - imageAdapter = EditableImageAdapter(this, 3, 3f) + imageAdapter = EditableImageAdapter(this, 3, 3) binding.cameraInclude.addImageRecyclerView.adapter = imageAdapter taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] @@ -308,8 +302,8 @@ weakReferenceHandler.postDelayed({ try { // 发送读标识器或搜索信号 - outputStream?.write("2".toByteArray()) - outputStream?.flush() + out.write("2".toByteArray()) + out.flush() } catch (e: IOException) { e.printStackTrace() } @@ -317,7 +311,7 @@ } } - override fun onDataReceived(buffer: ByteArray?, size: Int) { + override fun onDataReceived(buffer: ByteArray) { if (buffer != null) { val message = weakReferenceHandler.obtainMessage() message.what = 2023081702 diff --git a/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt b/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt index 44d56ef..9c98b5f 100644 --- a/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt @@ -1,36 +1,29 @@ package com.casic.electric.detector.view import android.os.Bundle -import android.util.Log import androidx.lifecycle.ViewModelProvider import com.amap.api.navi.NaviSetting import com.casic.electric.detector.databinding.ActivityLoginBinding -import com.casic.electric.detector.extensions.initLayoutImmersionBar -import com.casic.electric.detector.utils.GpioManager -import com.casic.electric.detector.utils.LoadingDialogHub import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.vm.UserViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.getScreenHeight -import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog class LoginActivity : KotlinBaseActivity() { private val kTag = "LoginActivity" private lateinit var userViewModel: UserViewModel - private val gpioManager by lazy { GpioManager() } override fun initViewBinding(): ActivityLoginBinding { return ActivityLoginBinding.inflate(layoutInflater) } override fun initOnCreate(savedInstanceState: Bundle?) { - gpioManager.setGpioLow("18") //先把导航隐私政策声明,后面导航会用到 NaviSetting.updatePrivacyShow(this, true, true) NaviSetting.updatePrivacyAgree(this, true) @@ -60,11 +53,8 @@ val serversIp = binding.serversIpView.text.toString() val serversPort = binding.serversPortView.text.toString() if (account.isBlank() || password.isBlank() || serversIp.isBlank() || serversPort.isBlank()) { - AlertMessageDialog.Builder() - .setContext(this) - .setTitle("账号登录") - .setMessage("信息不能为空哦!") - .setPositiveButton("知道了") + AlertMessageDialog.Builder().setContext(this).setTitle("账号登录") + .setMessage("信息不能为空哦!").setPositiveButton("知道了") .setOnDialogButtonClickListener(object : AlertMessageDialog.OnDialogButtonClickListener { override fun onConfirmClick() { @@ -102,9 +92,6 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(true).init() - initLayoutImmersionBar(binding.rootView) - - Log.d(kTag, "setupTopBarLayout => [${getScreenWidth()}, ${getScreenHeight()}]") } override fun onResume() { diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt b/app/src/main/java/com/casic/electric/detector/extensions/Context.kt deleted file mode 100644 index fcf36a7..0000000 --- a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.casic.electric.detector.extensions - -import android.content.Context -import android.view.ViewGroup -import com.pengxh.kt.lite.extensions.getStatusBarHeight - -/** - * 设置沉浸式状态栏,兼容Android 11+ - * */ -fun Context.initLayoutImmersionBar(rootView: ViewGroup) { - rootView.setPadding(0, this.getStatusBarHeight(), 0, 0) - rootView.requestLayout() -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt index 6e08b27..e98408a 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt @@ -13,12 +13,4 @@ paint.color = color canvas.drawArc(rectF, 0f, 360f, true, paint) return bitmap -} - -fun Int.appendZero(): String { - return if (this < 10) { - "0$this" - } else { - this.toString() - } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/String.kt b/app/src/main/java/com/casic/electric/detector/extensions/String.kt index a0db0eb..838d3ad 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/String.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/String.kt @@ -3,14 +3,11 @@ import android.content.Context import android.widget.TextView import com.casic.electric.detector.callback.OnImageCompressListener -import com.casic.electric.detector.model.ErrorMessageModel import com.casic.electric.detector.utils.FileType import com.casic.electric.detector.utils.LocaleConstant -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken +import com.google.gson.JsonParser import com.pengxh.kt.lite.extensions.createCompressImageDir import com.pengxh.kt.lite.utils.SaveKeyValues -import org.json.JSONObject import top.zibin.luban.Luban import top.zibin.luban.OnCompressListener import java.io.File @@ -18,18 +15,22 @@ /** * String扩展方法 */ -fun String.separateResponseState(): Boolean { +fun String.getResponseState(): Boolean { if (this.isBlank()) { return false } - return JSONObject(this).getBoolean("success") + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("success").asBoolean } -fun String.toErrorMessage(): String { - val errorModel = Gson().fromJson( - this, object : TypeToken() {}.type - ) - return errorModel.message.toString() +fun String.getResponseMessage(): String { + if (this.isBlank()) { + return "" + } + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("message").asString } /** @@ -131,4 +132,9 @@ } else { "6" } +} + +fun String.isNumber(): Boolean { + val regex = Regex("[-+]?\\d+(\\.\\d+)?") + return this.matches(regex) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt new file mode 100644 index 0000000..8b78a3c --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt @@ -0,0 +1,31 @@ +package com.casic.electric.detector.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import androidx.fragment.app.Fragment +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} + +fun ViewGroup.initImmersionBar(fragment: Fragment, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(fragment) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(fragment.requireContext())) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = fragment.requireContext().getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt new file mode 100644 index 0000000..84c9cd9 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt @@ -0,0 +1,3 @@ +package com.casic.electric.detector.model + +data class CalculateResult(val angle: Int, val direction: String, val distance: Int) diff --git a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java b/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java deleted file mode 100644 index 1574393..0000000 --- a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.casic.electric.detector.model; - -public class ErrorMessageModel { - private int code; - private String data; - private String exceptionClazz; - private String message; - private boolean isSuccess; - - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public String getExceptionClazz() { - return exceptionClazz; - } - - public void setExceptionClazz(String exceptionClazz) { - this.exceptionClazz = exceptionClazz; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public boolean isSuccess() { - return isSuccess; - } - - public void setSuccess(boolean success) { - isSuccess = success; - } -} diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt index 950fb91..f590226 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt @@ -90,10 +90,25 @@ /** * 上传工单中标识器信息 + * info中的主键 */ @GET("/ems/rs/task/update-task-mark") suspend fun uploadMarker( - @Query("userName") userId: String, - @Query("taskDetailId") taskId: String, + @Query("taskDetailId") taskId: String ): String + + /** + * 新建自由巡检任务 + * */ + @GET("ems/rs/task/addAppTask") + suspend fun createFreeTask( + @Query("patrollerId") patrollerId: String, + @Query("description") description: String + ): String + + /** + * 上传自由巡检过程中发现的标识器 + * */ + @POST("ems/event/uploadAppMarker.do") + suspend fun uploadTaskMarker(@Body requestBody: RequestBody): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt index 6834fc5..7836b28 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt @@ -1,5 +1,6 @@ package com.casic.electric.detector.retrofit +import com.casic.electric.detector.extensions.reformat import com.casic.electric.detector.utils.LabelDataClass import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.SmallLabelDataClass @@ -15,43 +16,32 @@ object RetrofitServiceManager { + private fun createApi(): RetrofitService { + val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String + val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String + val httpConfig = "http://${serverIp}:${serverPort}" + return RetrofitFactory.createRetrofit(httpConfig) + } + /** * 登录 */ suspend fun login(account: String, password: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.login(account, password) + return createApi().login(account, password) } /** * 更新版本 * */ suspend fun getApplicationVersion(): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getApplicationVersion() + return createApi().getApplicationVersion() } /** * 获取标识器信息文件 */ suspend fun getMarkerFile(userId: String, companyId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getMarkerFile(userId, companyId) + return createApi().getMarkerFile(userId, companyId) } /** @@ -64,39 +54,21 @@ "application/json;charset=UTF-8".toMediaType() ) - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getLabelPicture(requestBody) + return createApi().getLabelPicture(requestBody) } /** * 获取巡检工单 */ suspend fun getTask(userName: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getTask(userName) + return createApi().getTask(userName) } /** * 提交工单 */ suspend fun uploadTask(userId: String, taskId: String?, state: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadTask(userId, taskId.toString(), state) + return createApi().uploadTask(userId, taskId.toString(), state) } /** @@ -164,27 +136,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installLabel(res, multiParts[0], multiParts[1], null) + createApi().installLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installLabel(res, multiParts[0], null, null) + createApi().installLabel(res, multiParts[0], null, null) } else -> { - api.installLabel(res, null, null, null) + createApi().installLabel(res, null, null, null) } } } @@ -230,27 +196,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], null) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installSmallLabel(res, multiParts[0], null, null) + createApi().installSmallLabel(res, multiParts[0], null, null) } else -> { - api.installSmallLabel(res, null, null, null) + createApi().installSmallLabel(res, null, null, null) } } } @@ -279,27 +239,23 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2]) + createApi().uploadEvent( + taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2] + ) } 2 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) } 1 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) } else -> { - api.uploadEvent(taskIdMap, eventMap, null, null, null) + createApi().uploadEvent(taskIdMap, eventMap, null, null, null) } } } @@ -307,13 +263,27 @@ /** * 上传工单中标识器信息 */ - suspend fun uploadMarker(userName: String, taskDetailId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadMarker(userName, taskDetailId) + suspend fun uploadMarker(taskDetailId: String): String { + return createApi().uploadMarker(taskDetailId) + } + + /** + * 上传工单中标识器信息 + */ + suspend fun createFreeTask(patrollerId: String, description: String): String { + return createApi().createFreeTask(patrollerId, description) + } + + /** + * 上传自由巡检过程中发现的标识器 + */ + suspend fun uploadTaskMarker(taskId: String, models: ArrayList): String { + val param = JsonObject() + param.addProperty("taskId", taskId) + param.addProperty("ids", models.reformat()) + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return createApi().uploadTaskMarker(requestBody) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java index 4aba809..45d5a2f 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java +++ b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java @@ -1,8 +1,10 @@ package com.casic.electric.detector.utils; -public class GpioManager { +import android.util.Log; +public class GpioManager { + private static final String TAG = "GpioManager"; private static final int MT6761 = 0; private int selected; private final MT6761Gpio mt6761; @@ -38,6 +40,7 @@ * 璁剧疆GPIO杈撳嚭楂� * *********************************************************************/ public void setGpioHigh(String gpio) { + Log.d(TAG, "setGpioHigh: 调高电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioHigh(); @@ -48,6 +51,7 @@ * 璁剧疆GPIO杈撳嚭浣� * *********************************************************************/ public void setGpioLow(String gpio) { + Log.d(TAG, "setGpioLow: 调低电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioLow(); diff --git a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt deleted file mode 100644 index c589c4b..0000000 --- a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.electric.detector.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt index 4de12f2..9356f9a 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt @@ -13,7 +13,7 @@ ) const val PERMISSIONS_CODE = 999 - const val RADIUS_SIZE = 100f //相距多少米才聚合,单位:米 + const val RADIUS_SIZE = 100 //相距多少米才聚合,单位:米 const val AUTO_SAVE = "AUTO_SAVE" const val USER_ACCOUNT = "USER_ACCOUNT" @@ -28,10 +28,21 @@ const val APP_AUTHORITY = "com.casic.electric.detector.fileprovider" val POPUP_TITLES = arrayOf("更新数据", "下载工单", "关于软件", "事件上报", "标识器补全") - var CONDITION_ARRAY = arrayOf("种类", "编号", "名称", "所属区域", "所属道路", "运检单位", "责任人", "建设时间", "标识器ID") + var CONDITION_ARRAY = arrayOf( + "种类", + "编号", + "名称", + "所属区域", + "所属道路", + "运检单位", + "责任人", + "建设时间", + "标识器ID" + ) var CONTENT_ARRAY = arrayOf("电缆井", "电缆通道", "配电房", "开关站", "台区", "杆塔") var OBJECT_MODE_ARRAY = arrayOf("直线井", "转弯井", "丁字井", "十字井", "其他") - var WELL_COVER_MATERIAL_ARRAY_1 = arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") + var WELL_COVER_MATERIAL_ARRAY_1 = + arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") var WELL_COVER_MATERIAL_ARRAY_2 = arrayOf("水泥杆", "钢管杆", "铁塔", "其他") var CABINET_TYPE_ARRAY = arrayOf("无", "SM6", "SAFE", "RM6", "XGN15", "固体柜") var PIPE_MATERIAL_ARRAY = arrayOf("无", "PVC管", "波纹管", "镀锌钢管") @@ -42,7 +53,16 @@ var CROSS_PIPE_STATE_ARRAY = booleanArrayOf(false, false, false, false, false, false, false) var POINT_TYPE_ARRAY = arrayOf("管线", "管线附属物", "管线特征管点", "交叉穿越点") - var SPINNER_ARRAY = arrayOf("标识器ID", "所属区域", "所属线路", "所属道路", "权属单位", "安装部门", "安装时间", "备注") + var SPINNER_ARRAY = arrayOf( + "标识器ID", + "所属区域", + "所属线路", + "所属道路", + "权属单位", + "安装部门", + "安装时间", + "备注" + ) var DOWN_PIPE_TYPE_ARRAY = arrayOf("热力", "燃气", "供水", "电力", "通信") var BURY_METHOD_ARRAY = arrayOf("直埋", "圆管", "管块", "管沟", "架空") var COLOR_ARRAY = arrayOf("蓝色", "橙色", "红色", "黑色", "紫色", "黄色", "绿色") diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt index 4f0f2c7..61e55f6 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt @@ -14,14 +14,16 @@ import com.casic.electric.detector.callback.IAddressListener import com.casic.electric.detector.callback.ILocationListener -object LocationHub { - private const val kTag = "LocationHub" +class LocationHub constructor(context: Context) { - fun getCurrentLocation(context: Context, listener: ILocationListener) { - val locationClient = AMapLocationClient(context) + private val kTag = "LocationHub" + private val locationClient by lazy { AMapLocationClient(context) } + private val codeSearch by lazy { GeocodeSearch(context) } + + fun getCurrentLocation(isOnceLocation: Boolean, listener: ILocationListener) { val locationOption = AMapLocationClientOption() locationOption.locationMode = AMapLocationClientOption.AMapLocationMode.Hight_Accuracy - locationOption.isOnceLocation = true + locationOption.isOnceLocation = isOnceLocation locationClient.setLocationOption(locationOption) locationClient.setLocationListener { if (it.errorCode == 0) { @@ -36,9 +38,8 @@ locationClient.startLocation() } - fun antiCodingLocation(context: Context, location: Location, listener: IAddressListener) { + fun antiCodingLocation(location: Location, listener: IAddressListener) { try { - val codeSearch = GeocodeSearch(context) // 第一个参数表示一个LatLonPoint,第二参数表示范围多少米,第三个参数表示是火系坐标系还是GPS原生坐标系 val query = RegeocodeQuery( LatLonPoint(location.latitude, location.longitude), 10f, GeocodeSearch.AMAP @@ -55,4 +56,8 @@ e.printStackTrace() } } + + fun stopLocation() { + locationClient.stopLocation() + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt b/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt index aa1bdeb..e3d3289 100644 --- a/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt @@ -1,7 +1,6 @@ package com.casic.electric.detector.view import android.content.Context -import android.graphics.Color import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -12,10 +11,10 @@ import com.bumptech.glide.Glide import com.casic.electric.detector.R import com.casic.electric.detector.databinding.ActivityBigImageBinding +import com.casic.electric.detector.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class BigImageActivity : KotlinBaseActivity() { @@ -24,20 +23,12 @@ } override fun setupTopBarLayout() { - ImmerseStatusBarUtil.setColor(this, Color.BLACK) + binding.rootView.initImmersionBar(this, false, R.color.black) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - val index: Int = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return @@ -62,6 +53,14 @@ }) } + override fun observeRequestState() { + + } + + override fun initEvent() { + + } + inner class BigImageAdapter( private val context: Context, private val data: ArrayList ) : PagerAdapter() { diff --git a/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt b/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt index d3a89ca..6510104 100644 --- a/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt @@ -29,15 +29,15 @@ import com.casic.electric.detector.extensions.* import com.casic.electric.detector.utils.* import com.casic.electric.detector.vm.TaskViewModel -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia import com.luck.picture.lib.interfaces.OnResultCallbackListener import com.pengxh.kt.lite.extensions.* +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -53,7 +53,8 @@ private val context: Context = this@InstallLabelActivity private val gpioManager by lazy { GpioManager() } private val calendar by lazy { Calendar.getInstance() } - private val realPaths: ArrayList = ArrayList() //真实图片路径 + private val locationHub by lazy { LocationHub(this) } + private val realPaths = ArrayList() //真实图片路径 private var soundResId = 0 private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var soundPool: SoundPool @@ -67,12 +68,6 @@ override fun setupTopBarLayout() { binding.titleInclude.titleView.text = "安装新标识器" binding.titleInclude.titleView.setTextColor(R.color.themeColor.convertColor(this)) - - ImmersionBar.with(this) - .statusBarDarkFont(true) - .statusBarColor(R.color.mainBackground) - .init() - initLayoutImmersionBar(binding.rootView) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -126,7 +121,7 @@ binding.markerAttrInclude.remarkView3.setText("remarkView3".getDefaultValue()) //初始化图片九宫格 - imageAdapter = EditableImageAdapter(this, 3, 3f) + imageAdapter = EditableImageAdapter(this, 3, 3) binding.cameraInclude.addImageRecyclerView.adapter = imageAdapter taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] @@ -332,7 +327,7 @@ binding.markerAttrInclude.installTimeView.text = System.currentTimeMillis().timestampToCompleteDate() - LocationHub.getCurrentLocation(this, object : ILocationListener { + locationHub.getCurrentLocation(true, object : ILocationListener { override fun onAMapLocationGet(location: AMapLocation?) { if (location != null) { binding.markerAttrInclude.lngView.text = location.longitude.toString() @@ -518,8 +513,8 @@ weakReferenceHandler.postDelayed({ try { // 发送读标识器或搜索信号 - outputStream?.write("2".toByteArray()) - outputStream?.flush() + out.write("2".toByteArray()) + out.flush() } catch (e: IOException) { e.printStackTrace() } @@ -527,7 +522,7 @@ } } - override fun onDataReceived(buffer: ByteArray?, size: Int) { + override fun onDataReceived(buffer: ByteArray) { Log.d(kTag, "onDataReceived => " + buffer.contentToString()) if (buffer != null) { val message = weakReferenceHandler.obtainMessage() diff --git a/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt b/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt index 5bc2ac8..286bf4a 100644 --- a/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt @@ -24,7 +24,6 @@ import com.casic.electric.detector.extensions.* import com.casic.electric.detector.utils.* import com.casic.electric.detector.vm.TaskViewModel -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -33,9 +32,10 @@ import com.pengxh.kt.lite.extensions.isNetworkConnected import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -65,12 +65,6 @@ override fun setupTopBarLayout() { binding.titleInclude.titleView.text = "安装新电子标签" binding.titleInclude.titleView.setTextColor(R.color.themeColor.convertColor(this)) - - ImmersionBar.with(this) - .statusBarDarkFont(true) - .statusBarColor(R.color.mainBackground) - .init() - initLayoutImmersionBar(binding.rootView) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -103,7 +97,7 @@ binding.objectAttrInclude.objectRemarkView3.setText("objectRemarkView3".getDefaultValue()) //初始化图片九宫格 - imageAdapter = EditableImageAdapter(this, 3, 3f) + imageAdapter = EditableImageAdapter(this, 3, 3) binding.cameraInclude.addImageRecyclerView.adapter = imageAdapter taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] @@ -308,8 +302,8 @@ weakReferenceHandler.postDelayed({ try { // 发送读标识器或搜索信号 - outputStream?.write("2".toByteArray()) - outputStream?.flush() + out.write("2".toByteArray()) + out.flush() } catch (e: IOException) { e.printStackTrace() } @@ -317,7 +311,7 @@ } } - override fun onDataReceived(buffer: ByteArray?, size: Int) { + override fun onDataReceived(buffer: ByteArray) { if (buffer != null) { val message = weakReferenceHandler.obtainMessage() message.what = 2023081702 diff --git a/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt b/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt index 44d56ef..9c98b5f 100644 --- a/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt @@ -1,36 +1,29 @@ package com.casic.electric.detector.view import android.os.Bundle -import android.util.Log import androidx.lifecycle.ViewModelProvider import com.amap.api.navi.NaviSetting import com.casic.electric.detector.databinding.ActivityLoginBinding -import com.casic.electric.detector.extensions.initLayoutImmersionBar -import com.casic.electric.detector.utils.GpioManager -import com.casic.electric.detector.utils.LoadingDialogHub import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.vm.UserViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.getScreenHeight -import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog class LoginActivity : KotlinBaseActivity() { private val kTag = "LoginActivity" private lateinit var userViewModel: UserViewModel - private val gpioManager by lazy { GpioManager() } override fun initViewBinding(): ActivityLoginBinding { return ActivityLoginBinding.inflate(layoutInflater) } override fun initOnCreate(savedInstanceState: Bundle?) { - gpioManager.setGpioLow("18") //先把导航隐私政策声明,后面导航会用到 NaviSetting.updatePrivacyShow(this, true, true) NaviSetting.updatePrivacyAgree(this, true) @@ -60,11 +53,8 @@ val serversIp = binding.serversIpView.text.toString() val serversPort = binding.serversPortView.text.toString() if (account.isBlank() || password.isBlank() || serversIp.isBlank() || serversPort.isBlank()) { - AlertMessageDialog.Builder() - .setContext(this) - .setTitle("账号登录") - .setMessage("信息不能为空哦!") - .setPositiveButton("知道了") + AlertMessageDialog.Builder().setContext(this).setTitle("账号登录") + .setMessage("信息不能为空哦!").setPositiveButton("知道了") .setOnDialogButtonClickListener(object : AlertMessageDialog.OnDialogButtonClickListener { override fun onConfirmClick() { @@ -102,9 +92,6 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(true).init() - initLayoutImmersionBar(binding.rootView) - - Log.d(kTag, "setupTopBarLayout => [${getScreenWidth()}, ${getScreenHeight()}]") } override fun onResume() { diff --git a/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt b/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt index 36a8d55..a0a4aac 100644 --- a/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt @@ -1,15 +1,21 @@ package com.casic.electric.detector.view +import android.annotation.SuppressLint import android.app.AlertDialog +import android.app.Dialog import android.content.Context -import android.content.Intent import android.graphics.Color import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable +import android.media.AudioAttributes +import android.media.SoundPool import android.os.Bundle -import android.os.PowerManager -import android.provider.Settings +import android.os.CountDownTimer +import android.util.Log import android.view.KeyEvent +import android.view.View +import android.view.animation.Animation +import android.view.animation.RotateAnimation import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import com.amap.api.location.AMapLocation @@ -21,6 +27,8 @@ import com.amap.api.maps.model.LatLngBounds import com.amap.api.maps.model.MyLocationStyle import com.casic.electric.detector.R +import com.casic.electric.detector.adapter.EditableImageAdapter +import com.casic.electric.detector.base.SerialPortActivity import com.casic.electric.detector.bean.LabelBean import com.casic.electric.detector.bean.SmallLabelBean import com.casic.electric.detector.bean.TaskBean @@ -29,83 +37,109 @@ import com.casic.electric.detector.cluster.ClusterOverlay import com.casic.electric.detector.cluster.RegionItem import com.casic.electric.detector.databinding.ActivityMainBinding +import com.casic.electric.detector.databinding.DialogInstallMarkerBinding +import com.casic.electric.detector.databinding.DialogInstallSmallMarkerBinding +import com.casic.electric.detector.databinding.DialogSearchMarkerBinding import com.casic.electric.detector.extensions.appendExcelDownloadUrl import com.casic.electric.detector.extensions.drawCircle -import com.casic.electric.detector.extensions.initLayoutImmersionBar +import com.casic.electric.detector.extensions.hexToString +import com.casic.electric.detector.extensions.initImmersionBar +import com.casic.electric.detector.extensions.isNumber +import com.casic.electric.detector.extensions.toHex import com.casic.electric.detector.utils.DataBaseManager import com.casic.electric.detector.utils.ExcelHub -import com.casic.electric.detector.utils.LoadingDialogHub +import com.casic.electric.detector.utils.GpioManager import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.LocationHub import com.casic.electric.detector.utils.RouteOnMap import com.casic.electric.detector.vm.TaskViewModel import com.casic.electric.detector.widgets.QueryMarkerDialog import com.casic.electric.detector.widgets.SamplePopupWindow -import com.gyf.immersionbar.ImmersionBar -import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.callback.OnDownloadListener +import com.google.gson.Gson +import com.pengxh.kt.lite.extensions.binding import com.pengxh.kt.lite.extensions.createDownloadFileDir -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.dp2px +import com.pengxh.kt.lite.extensions.initDialogLayoutParams import com.pengxh.kt.lite.extensions.isNetworkConnected import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.toJson +import com.pengxh.kt.lite.utils.FileDownloadManager +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog +import com.pengxh.kt.lite.widget.dialog.AlertInputDialog +import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File +import java.text.DecimalFormat +import java.util.Calendar +import java.util.Timer +import java.util.TimerTask -class MainActivity : KotlinBaseActivity() { +@SuppressLint("all") +class MainActivity : SerialPortActivity() { private val kTag = "MainActivity" - private val context: Context = this@MainActivity + private val context = this@MainActivity + private val gpioManager by lazy { GpioManager() } private val samplePopupWindow by lazy { SamplePopupWindow(this) } + private val gson by lazy { Gson() } + private val locationHub by lazy { LocationHub(this) } + private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } + private val backDrawables by lazy { HashMap() } + private val installMarkerDialog by lazy { InstallMarkerDialog(this) } + private val installSmallMarkerDialog by lazy { InstallSmallMarkerDialog(this) } + private val searchDialog by lazy { SearchMarkerDialog(this) } private var clickTime: Long = 0 - private lateinit var wakeLock: PowerManager.WakeLock - private lateinit var aMap: AMap - private lateinit var taskViewModel: TaskViewModel - private lateinit var taskBean: TaskBean - private var latitude: Double = 0.0 - private var longitude: Double = 0.0 private var labels = ArrayList() private var smallLabels = ArrayList() private var clusterOverlay: ClusterOverlay? = null - private val backDrawables = HashMap() - private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } + private var latitude: Double = 0.0 + private var longitude: Double = 0.0 + private var isFreeTask = false + private var ids = ArrayList() + private var signalTask: TimerTask? = null + private var searchMarkerTimer: Timer? = null + private lateinit var aMap: AMap + private lateinit var taskBean: TaskBean + private lateinit var taskId: String + + /***inner class 需要用到*****start*/ + private val taskViewModel by lazy { ViewModelProvider(this)[TaskViewModel::class.java] } + 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 var soundResourceId = 0 + private var slowSoundResourceId = 0 + private var fastSoundResourceId = 0 + + /***inner class 需要用到*****end*/ override fun initViewBinding(): ActivityMainBinding { return ActivityMainBinding.inflate(layoutInflater) } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).statusBarColor(R.color.themeColor).init() - initLayoutImmersionBar(binding.rootView) - } - - override fun observeRequestState() { - + binding.rootView.initImmersionBar(this, false, R.color.themeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { - val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager - wakeLock = powerManager.run { - newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this@MainActivity.localClassName).apply { - acquire(60 * 60 * 1000L) - } - } + soundResourceId = soundPool.load(this, R.raw.ring3, 1) + slowSoundResourceId = soundPool.load(this, R.raw.ring4, 1) + fastSoundResourceId = soundPool.load(this, R.raw.ring2, 1) + //地图初始化 initMapConfig(savedInstanceState) samplePopupWindow.setPopupMenuItem(LocaleConstant.POPUP_TITLES) samplePopupWindow.setBackgroundDrawable(null) - taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] + //task网络请求监听 taskViewModel.markerFileResult.observe(this) { if (it.success == "true") { //清空之前的数据 @@ -122,11 +156,13 @@ val smallLabelDownloadUrl = urlArray[1].appendExcelDownloadUrl() //下载标识器 - labelDownloadUrl.downloadFile( - createDownloadFileDir().toString(), object : OnDownloadListener { - override fun onDownloadEnd(file: File?) { + FileDownloadManager.Builder().setDownloadFileSource(labelDownloadUrl) + .setFileSuffix("xls").setFileSaveDirectory(createDownloadFileDir()) + .setOnFileDownloadListener(object : + FileDownloadManager.OnFileDownloadListener { + override fun onDownloadEnd(file: File) { lifecycleScope.launch { - labels = ExcelHub.readLabel(file?.absolutePath) + labels = ExcelHub.readLabel(file.absolutePath) withContext(Dispatchers.IO) { labels.forEach { label -> DataBaseManager.get.insertLabel(label) @@ -137,21 +173,23 @@ } } - override fun onDownloadStart(totalBytes: Long) { + override fun onFailure(throwable: Throwable) { } - override fun onProgressChanged(currentBytes: Long) { + override fun onProgressChanged(progress: Int) { } - }) + }).build().start() //下载附属标识器 - smallLabelDownloadUrl.downloadFile( - createDownloadFileDir().toString(), object : OnDownloadListener { - override fun onDownloadEnd(file: File?) { + FileDownloadManager.Builder().setDownloadFileSource(smallLabelDownloadUrl) + .setFileSuffix("xls").setFileSaveDirectory(createDownloadFileDir()) + .setOnFileDownloadListener(object : + FileDownloadManager.OnFileDownloadListener { + override fun onDownloadEnd(file: File) { lifecycleScope.launch { - smallLabels = ExcelHub.readSmallLabel(file?.absolutePath) + smallLabels = ExcelHub.readSmallLabel(file.absolutePath) withContext(Dispatchers.IO) { smallLabels.forEach { label -> DataBaseManager.get.insertSmallLabel(label) @@ -160,14 +198,14 @@ } } - override fun onDownloadStart(totalBytes: Long) { + override fun onFailure(throwable: Throwable) { } - override fun onProgressChanged(currentBytes: Long) { + override fun onProgressChanged(progress: Int) { } - }) + }).build().start() } } } @@ -175,11 +213,8 @@ // if (it.success == "true") { // //清空之前的数据 // DataBaseManager.get.clearTasks() -// AlertMessageDialog.Builder() -// .setContext(this) -// .setTitle("温馨提示") -// .setMessage("您有${it.message.size}个新任务!") -// .setPositiveButton("知道了") +// AlertMessageDialog.Builder().setContext(this).setTitle("温馨提示") +// .setMessage("您有${it.message.size}个新任务!").setPositiveButton("知道了") // .setOnDialogButtonClickListener(object : // AlertMessageDialog.OnDialogButtonClickListener { // override fun onConfirmClick() { @@ -188,19 +223,24 @@ // }).build().show() // } // } + taskViewModel.freeTaskResult.observe(this) { taskId = it } + taskViewModel.uploadTaskMarkerResult.observe(this) { + "自由巡检任务已完成".show(this) + ids.clear() + } } override fun initEvent() { binding.rightImageView.setOnClickListener { - CoroutineScope(Dispatchers.Main).launch { + lifecycleScope.launch(Dispatchers.Main) { val labels = withContext(Dispatchers.IO) { DataBaseManager.get.queryLabelById("0") } if (labels.isNotEmpty()) { samplePopupWindow.setShowPosition(4) } - val x = binding.rightImageView.width - samplePopupWindow.width - 1f.dp2px(context) - samplePopupWindow.showAsDropDown(binding.rightImageView, x, 1f.dp2px(context)) + val x = binding.rightImageView.width - samplePopupWindow.width - 1.dp2px(context) + samplePopupWindow.showAsDropDown(binding.rightImageView, x, 1.dp2px(context)) } } @@ -219,35 +259,33 @@ //安装。上传,然后存入本地库 binding.installButton.setOnClickListener { - AlertControlDialog.Builder() - .setContext(context) - .setTitle("提示") - .setMessage("请选择安装对象") - .setPositiveButton("标识器") - .setNegativeButton("电子标签") - .setOnDialogButtonClickListener(object : + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("请选择安装对象").setPositiveButton("标识器") + .setNegativeButton("电子标签").setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { //标识器 - navigatePageTo() + /** + * 改为Dialog方式,避免频繁打开/关闭串口 + * */ + installMarkerDialog.show() } override fun onCancelClick() { //电子标签 - navigatePageTo() + /** + * 改为Dialog方式,避免频繁打开/关闭串口 + * */ + installSmallMarkerDialog.show() } }).build().show() } //查看 binding.viewButton.setOnClickListener { - QueryMarkerDialog.Builder() - .setContext(this) - .setTitle("查看标识器") - .setConditionArray(LocaleConstant.CONDITION_ARRAY) - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : + QueryMarkerDialog.Builder().setContext(this).setTitle("查看标识器") + .setConditionArray(LocaleConstant.CONDITION_ARRAY).setNegativeButton("取消") + .setPositiveButton("确定").setOnDialogButtonClickListener(object : QueryMarkerDialog.OnDialogButtonClickListener { override fun onConfirmClick( selectedCondition: String, vararg contentValue: String @@ -310,30 +348,25 @@ // arrayList.add("任务${index + 1}:${taskBean.taskId},${taskBean.desc}") // } // -// BottomActionSheet.Builder() -// .setContext(this) -// .setItemTextColor(Color.BLUE) +// BottomActionSheet.Builder().setContext(this).setItemTextColor(Color.BLUE) // .setActionItemTitle(arrayList) // .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { // override fun onActionItemClick(position: Int) { // val taskBean = task[position] // SaveKeyValues.putValue(LocaleConstant.TASK_ID, taskBean.taskId) -// AlertControlDialog.Builder() -// .setContext(context) -// .setTitle("提示") -// .setMessage("请选择操作方式") -// .setPositiveButton("执行工单") +// AlertControlDialog.Builder().setContext(context).setTitle("提示") +// .setMessage("请选择操作方式").setPositiveButton("执行工单") // .setNegativeButton("提交工单") // .setOnDialogButtonClickListener(object : // AlertControlDialog.OnDialogButtonClickListener { // override fun onConfirmClick() { // detectRedrawGraphic(taskBean.taskId) +// +// val latLng = LatLng( +// taskBean.lat.toDouble(), taskBean.lng.toDouble() +// ) // aMap.moveCamera( -// CameraUpdateFactory.newLatLngZoom( -// LatLng( -// taskBean.lat.toDouble(), taskBean.lng.toDouble() -// ), 15f -// ) +// CameraUpdateFactory.newLatLngZoom(latLng, 16f) // ) // uploadTask(taskBean.taskId, "1") // } @@ -345,15 +378,12 @@ // } // }).build().show() // } else { -// AlertMessageDialog.Builder() -// .setContext(this) -// .setTitle("温馨提示") -// .setMessage("现有任务已完成,请点击右上角菜单按钮下载新工单!") -// .setPositiveButton("知道了") -// .setOnDialogButtonClickListener(object : +// AlertMessageDialog.Builder().setContext(this).setTitle("温馨提示") +// .setMessage("现有任务已完成,请点击右上角菜单下载新工单或者开始自由巡检") +// .setPositiveButton("知道了").setOnDialogButtonClickListener(object : // AlertMessageDialog.OnDialogButtonClickListener { // override fun onConfirmClick() { -// +// startFreeTask() // } // }).build().show() // } @@ -361,7 +391,118 @@ //探测 binding.detectionButton.setOnClickListener { -// navigatePageTo() + /** + * 改为Dialog方式,避免频繁打开/关闭串口 + * */ + searchDialog.show() + } + + //自由巡检 + binding.stopFreeTaskButton.setOnLongClickListener { + AlertMessageDialog.Builder().setContext(this).setTitle("温馨提示") + .setMessage("是否确定结束此次自由巡检任务?").setPositiveButton("是") + .setOnDialogButtonClickListener(object : + AlertMessageDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + isFreeTask = false + soundPool.autoPause() + + //降低串口电位 + gpioManager.setGpioLow("18") + + taskViewModel.uploadTaskMarker(taskId, ids) + binding.stopFreeTaskButton.visibility = View.GONE + } + }).build().show() + true + } + } + + private fun startFreeTask() { + AlertInputDialog.Builder().setContext(this).setTitle("新建自由巡检任务") + .setHintMessage("请输入自由巡检任务简要描述").setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : AlertInputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String + taskViewModel.createFreeTask(userId, value) + + //调高串口电位 + gpioManager.setGpioHigh("18") + + soundPool.play(soundResourceId, 1f, 1f, 0, -1, 1f) + isFreeTask = true + //自由巡检 + signalTask = object : TimerTask() { + override fun run() { + out.write('2'.code) + out.flush() + } + } + searchMarkerTimer = Timer() + searchMarkerTimer?.apply { + schedule(signalTask, 0, 100) + } + + binding.stopFreeTaskButton.visibility = View.VISIBLE + } + + override fun onCancelClick() {} + }).build().show() + } + + override fun onDataReceived(buffer: ByteArray) { + val hex = buffer.toHex() + Log.d(kTag, "$kTag => $hex") + if (searchDialog.isDetectMarker) { + searchDialog.bindingValue(hex) +// } else if (installMarkerDialog.isReadMarker) { +// val markerId = hex.take(20).hexToString() +// if (markerId.isNumber()) { +// installMarkerDialog.bindingValue(markerId) +// } +// } else if (installSmallMarkerDialog.isReadMarker) { +// val markerId = hex.take(20).hexToString() +// if (markerId.isNumber()) { +// installSmallMarkerDialog.bindingValue(markerId) +// } + } else if (isFreeTask) { + val markerId = hex.take(20).hexToString() + if (markerId.isNumber()) { + "标识器${markerId}已探测".show(this) + ids.add(markerId) + } + } + } + + override fun observeRequestState() { + taskViewModel.loadState.observe(this) { + when (it) { + LoadState.Loading -> { + if (installMarkerDialog.isInstallMarker || installSmallMarkerDialog.isInstallMarker) { + LoadingDialogHub.show(this, "标识器安装中,请稍后...") + } else if (searchDialog.isDetectMarker) { + searchDialog.taskBean?.apply { + "标识器${this.markerId}已探测!".show(context) +// DataBaseManager.get.updateTaskLabel(this) + } + } else { + LoadingDialogHub.show(this, "提交工单中,请稍后") + } + } + + else -> { + if (installMarkerDialog.isInstallMarker) { + installMarkerDialog.dismiss() + installMarkerDialog.isInstallMarker = false + } else if (installSmallMarkerDialog.isInstallMarker) { + installSmallMarkerDialog.dismiss() + installSmallMarkerDialog.isInstallMarker = false + } + LoadingDialogHub.dismiss() + } + } + detectRedrawGraphic(taskBean.taskId) } } @@ -375,6 +516,7 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜 //显示定位小蓝点 val locationStyle = MyLocationStyle() locationStyle.interval(2000) @@ -387,7 +529,7 @@ longitude = it.longitude latitude = it.latitude //经纬度逆编码 - LocationHub.antiCodingLocation(context, it) { address -> + locationHub.antiCodingLocation(it) { address -> binding.currentLocationView.text = address } } @@ -417,7 +559,7 @@ } private fun moveToCurrentLocation() { - LocationHub.getCurrentLocation(this, object : ILocationListener { + locationHub.getCurrentLocation(true, object : ILocationListener { override fun onAMapLocationGet(location: AMapLocation?) { if (location != null) { aMap.moveCamera( @@ -432,46 +574,35 @@ }) } - //更新数据 - private fun updateLabels() { - AlertControlDialog.Builder() - .setContext(this) - .setTitle("提示") - .setMessage("是否更新数据?") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onConfirmClick() { - if (isNetworkConnected()) { - val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") - val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") - - LoadingDialogHub.show(this@MainActivity, "获取标识器信息中,请稍后") - //TODO 设计如此,都传companyId - taskViewModel.getMarkerFile(companyId.toString(), companyId.toString()) - } else { - NoNetworkDialog.Builder() - .setContext(context) - .setOnDialogButtonClickListener(object : - NoNetworkDialog.OnDialogButtonClickListener { - override fun onButtonClick() { - val intent = Intent(Settings.ACTION_SETTINGS) - startActivity(intent) - } - }).build().show() - } - } - - override fun onCancelClick() { - - } - }).build().show() - } +// private fun saveTaskInformation(it: TaskModel) { +// val userName = SaveKeyValues.getValue(LocaleConstant.USER_NAME, "") as String +// if (it.message.size > 0) { +// it.message.forEach { messageModel -> +// val count = DataBaseManager.get.countTaskById(messageModel.id.toString()) +// if (count == 0) { +// messageModel.taskDetailInfos.forEach { info -> +// DataBaseManager.get.insertTaskInformation( +// userName, +// messageModel.description, +// info.taskId.toString(), +// info.id.toString(), +// info.markerId.toString(), +// info.markerIdReal.toString(), +// info.longitude.toString(), +// info.latitude.toString(), +// messageModel.status +// ) +// } +// } +// } +// "工单下载成功!".show(context) +// } +// } private fun showLabelsOnMap() { clusterOverlay?.onDestroy() val clusterItems = ArrayList() + labels.forEach { val latLng = LatLng(it.latitude.toDouble(), it.longitude.toDouble(), false) val regionItem = RegionItem(latLng, it.markerId.toString()) @@ -480,7 +611,7 @@ clusterOverlay = ClusterOverlay(context, aMap, clusterItems, regionRadius) clusterOverlay?.setClusterRender { clusterNum -> - val radius = 80f.dp2px(context) + val radius = 80.dp2px(context) if (clusterNum == 0) { var bitmapDrawable = backDrawables[0] if (bitmapDrawable == null) { @@ -546,9 +677,7 @@ val latLngBounds = builder.build() aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 0)) - BottomActionSheet.Builder() - .setContext(this) - .setItemTextColor(Color.BLUE) + BottomActionSheet.Builder().setContext(this).setItemTextColor(Color.BLUE) .setActionItemTitle(listOf("标识器信息", "附属电子标签信息", "到这里去")) .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { override fun onActionItemClick(position: Int) { @@ -578,12 +707,7 @@ showElectricMarkers(electricMarkers) } - 2 -> { - RouteOnMap.startNavigation( - context, item.tag, - LatLng(item.position.latitude, item.position.longitude) - ) - } + 2 -> RouteOnMap.startNavigation(context, item.tag, latLng) } } }).build().show() @@ -591,14 +715,74 @@ } private fun showElectricMarkers(markers: ArrayList) { - AlertDialog.Builder(context) - .setIcon(R.mipmap.ic_launcher) - .setTitle("电子标签列表") + AlertDialog.Builder(context).setIcon(R.mipmap.ic_launcher).setTitle("电子标签列表") .setSingleChoiceItems(markers.toTypedArray(), -1) { _, which -> navigatePageTo(markers[which]) }.show() } + private fun detectRedrawGraphic(taskId: String) { +// val tasks = DataBaseManager.get.queryTaskById(taskId) +// if (tasks.isNotEmpty()) { +// tasks.forEach { +// val latLng = LatLng(it.lat.toDouble(), it.lng.toDouble()) +// val otMarkerOptions = MarkerOptions() +// otMarkerOptions.position(latLng) +// otMarkerOptions.visible(true) // 设置可见 +// if (it.state == "未开始") { +// otMarkerOptions.icon( +// BitmapDescriptorFactory.fromBitmap( +// BitmapFactory.decodeResource(resources, R.mipmap.label_red1) +// ) +// ).period(99).title("工单标识器").snippet(it.markerId) +// } else { +// otMarkerOptions.icon( +// BitmapDescriptorFactory.fromBitmap( +// BitmapFactory.decodeResource(resources, R.mipmap.label_blue1) +// ) +// ).period(99).title("工单标识器").snippet(it.markerId) +// } +// aMap.addMarker(otMarkerOptions) +// } +// } + showLabelsOnMap() + } + + private fun uploadTask(taskId: String?, state: String) { + if (isNetworkConnected()) { + val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String + taskViewModel.uploadTask(userId, taskId, state) + } else { + "网络连接已断开,请检查".show(this) + } + } + + //更新数据 + private fun updateLabels() { + AlertControlDialog.Builder().setContext(this).setTitle("提示").setMessage("是否更新数据?") + .setNegativeButton("取消").setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + if (isNetworkConnected()) { + val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") + + LoadingDialogHub.show(this@MainActivity, "获取标识器信息中,请稍后") + /** + * 后台设计如此,都传companyId + * */ + taskViewModel.getMarkerFile(companyId.toString(), companyId.toString()) + } else { + "网络连接已断开,请检查".show(context) + } + } + + override fun onCancelClick() { + + } + }).build().show() + } + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { return if (keyCode == KeyEvent.KEYCODE_BACK) { if (System.currentTimeMillis() - clickTime > 2000) { @@ -643,8 +827,270 @@ } override fun onDestroy() { - wakeLock.release() super.onDestroy() binding.mapView.onDestroy() + signalTask?.cancel() + searchMarkerTimer?.cancel() + soundPool.release() + locationHub.stopLocation() + //降低串口电位 + gpioManager.setGpioLow("18") + } + + /**安装标识器对话框******************************************************************************/ + inner class InstallMarkerDialog(context: Context) : Dialog(context) { + + private val binding: DialogInstallMarkerBinding by binding() + private val calendar by lazy { Calendar.getInstance() } + private val realPaths = ArrayList() //真实图片路径 + private lateinit var imageAdapter: EditableImageAdapter + + var isReadMarker = false + var isInstallMarker = false + } + + /**安装小标签对话框******************************************************************************/ + inner class InstallSmallMarkerDialog(context: Context) : Dialog(context) { + + private val binding: DialogInstallSmallMarkerBinding by binding() + private val calendar by lazy { Calendar.getInstance() } + private val realPaths = ArrayList() //真实图片路径 + private lateinit var imageAdapter: EditableImageAdapter + + var isReadMarker = false + var isInstallMarker = false + } + + /**探测标识器对话框******************************************************************************/ + inner class SearchMarkerDialog(context: Context) : Dialog(context) { + + private val binding: DialogSearchMarkerBinding by binding() + private val decimal by lazy { DecimalFormat("0.0") } + private val degreeCache by lazy { HashMap() } + private var isPlaying = false + private var markerId = "" + private lateinit var searchMarkerTimer: Timer + private lateinit var signalTask: TimerTask + private lateinit var energyTask: TimerTask + private lateinit var countDownTimer: CountDownTimer + + var isDetectMarker = false + var taskBean: TaskBean? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.initDialogLayoutParams(1f) + binding.depthButton.setOnClickListener { + signalTask.cancel() + energyTask.cancel() + searchMarkerTimer.cancel() + + out.write('3'.code) +// val result = DataBaseManager.get.queryLabelById(markerId) +// if (result.isNotEmpty()) { +// val tag = when (result.first().identifierType) { +// "EM30" -> '7' +// "EM50" -> '8' +// "EM14" -> '9' +// else -> '1' +// } +// if (tag == '1') { +// "此标识器无法读取埋深!".show(context) +// } else { +// // 发送读取标识器埋设深度指令 +// LoadingDialogHub.show(this@MainActivity, "正在测距,请稍后...") +// out.write(tag.code) +// out.flush() +// countDownTimer = object : CountDownTimer(15 * 1000, 1000) { +// override fun onTick(millisUntilFinished: Long) { +// +// } +// +// override fun onFinish() { +// LoadingDialogHub.dismiss() +// "探测此标识器深度超时,请重试".show(context) +// initTimer() +// } +// } +// countDownTimer.start() +// } +// } else { +// "标识器未安装,安装成功后才可读取埋深!".show(context) +// } + } + + binding.markerInfoButton.setOnClickListener { + //查库 + val result = DataBaseManager.get.queryLabelById(markerId) + if (result.isNotEmpty()) { +// context.navigatePageTo(result.first().toJson()) + } else { +// context.navigatePageTo(markerId) + } + } + } + + override fun onStart() { + super.onStart() + //调高串口电位 + gpioManager.setGpioHigh("18") + + initTimer() + + isDetectMarker = true + + //角度 + degreeCache["lastDegree"] = 0f + } + + fun bindingValue(hex: String) { + if (hex.startsWith("4E")) { + try { + //4E转为String为N,代表能量值 + //用能量值转动表盘 + val energyResponse = hex.take(10).hexToString() + val energy = energyResponse.substring(1).toInt() + if (energy >= 4000) { + isPlaying = if (!isPlaying) { + soundPool.play(fastSoundResourceId, 1f, 1f, 0, 0, 1f) + true + } else { + soundPool.pause(fastSoundResourceId) + false + } + } else { + isPlaying = if (!isPlaying) { + soundPool.play(slowSoundResourceId, 1f, 1f, 0, 0, 1f) + true + } else { + soundPool.pause(slowSoundResourceId) + false + } + } + + binding.resultTextView.text = "信号能量值:${energyResponse}" + + //转换为转动的角度 + val degree = (energy.toFloat() / (50 * 100)) * 180 + binding.energyValueView.text = decimal.format(degree) + + degreeCache["lastDegree"]?.apply { + val animation = RotateAnimation( + this, degree, + Animation.RELATIVE_TO_SELF, 0.5f, + Animation.RELATIVE_TO_SELF, 0.5f + ) + animation.duration = 0 + animation.fillAfter = true + binding.needleView.startAnimation(animation) + } + + //保存旋转后的角度 + degreeCache["lastDegree"] = degree + + if (energy <= 700) {//18° + binding.energyTipsView.text = "标识器信号较弱,可能距离较远" + binding.energyTipsView.setTextColor(Color.parseColor("#8D1717")) + binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_red) + + binding.depthButton.isEnabled = false + binding.depthButton.setTextColor(Color.parseColor("#CCCCCC")) + binding.depthButton.setBackgroundResource(R.mipmap.left_button_disable) + binding.markerInfoButton.isEnabled = false + binding.markerInfoButton.setTextColor(Color.parseColor("#CCCCCC")) + binding.markerInfoButton.setBackgroundResource(R.mipmap.right_button_disable) + + binding.searchResultView.text = "未检测到标识器" + binding.searchResultView.setTextColor(Color.parseColor("#8D1717")) + binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_red) + } else if (energy >= 4100) {//148° + binding.energyTipsView.text = "标识器信号极强,可能在正下方" + binding.energyTipsView.setTextColor(Color.parseColor("#428d00")) + binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_green) + } else {//[18°,148°] + binding.energyTipsView.text = "已靠近标识器,请继续移动位置" + binding.energyTipsView.setTextColor(Color.parseColor("#8C5700")) + binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_yellow) + } + } catch (e: NumberFormatException) { + e.printStackTrace() + } + } else if (hex.startsWith("53")) { + LoadingDialogHub.dismiss() + countDownTimer.cancel() + try { + val depthResponse = hex.take(10).hexToString() + val depth = depthResponse.drop(2).toInt() + AlertMessageDialog.Builder().setContext(context).setTitle("温馨提示") + .setMessage("标识器埋深:${depth}厘米").setPositiveButton("知道了") + .setOnDialogButtonClickListener(object : + AlertMessageDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + initTimer() + } + }).build().show() + } catch (e: NumberFormatException) { + e.printStackTrace() + } + } else { + val id = hex.take(20).hexToString() + if (id.isNumber()) { + markerId = id + + binding.depthButton.isEnabled = true + binding.depthButton.setTextColor(Color.WHITE) + binding.depthButton.setBackgroundResource(R.mipmap.left_button_enable) + binding.markerInfoButton.isEnabled = true + binding.markerInfoButton.setTextColor(Color.WHITE) + binding.markerInfoButton.setBackgroundResource(R.mipmap.right_button_enable) + + binding.searchResultView.text = "已检测到标识器" + binding.searchResultView.setTextColor(Color.parseColor("#428d00")) + binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_green) + + //自动上传标识器 +// taskBean = DataBaseManager.get.queryTaskLabelByIdAndState(markerId, "未开始") +// taskBean?.apply { +// /** +// * 此taskCode是 [com.casic.detector.model.TaskModel.MessageModel.TaskDetailInfosModel] 里面的主键,也就是这个标签在数据库里面的主键 +// * */ +// taskViewModel.uploadMarker(taskCode) +// } + } + } + } + + private fun initTimer() { + searchMarkerTimer = Timer() + + signalTask = object : TimerTask() { + override fun run() { + out.write('2'.code) + out.flush() + } + } + + energyTask = object : TimerTask() { + override fun run() { + out.write('6'.code) + out.flush() + } + } + + //错开信号和能量定时器 + searchMarkerTimer.schedule(signalTask, 0, 201) + searchMarkerTimer.schedule(energyTask, 0, 251) + } + + override fun dismiss() { + signalTask.cancel() + energyTask.cancel() + searchMarkerTimer.cancel() + //降低串口电位 + gpioManager.setGpioLow("18") + isDetectMarker = false + soundPool.autoPause() + super.dismiss() + } } } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt b/app/src/main/java/com/casic/electric/detector/extensions/Context.kt deleted file mode 100644 index fcf36a7..0000000 --- a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.casic.electric.detector.extensions - -import android.content.Context -import android.view.ViewGroup -import com.pengxh.kt.lite.extensions.getStatusBarHeight - -/** - * 设置沉浸式状态栏,兼容Android 11+ - * */ -fun Context.initLayoutImmersionBar(rootView: ViewGroup) { - rootView.setPadding(0, this.getStatusBarHeight(), 0, 0) - rootView.requestLayout() -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt index 6e08b27..e98408a 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt @@ -13,12 +13,4 @@ paint.color = color canvas.drawArc(rectF, 0f, 360f, true, paint) return bitmap -} - -fun Int.appendZero(): String { - return if (this < 10) { - "0$this" - } else { - this.toString() - } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/String.kt b/app/src/main/java/com/casic/electric/detector/extensions/String.kt index a0db0eb..838d3ad 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/String.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/String.kt @@ -3,14 +3,11 @@ import android.content.Context import android.widget.TextView import com.casic.electric.detector.callback.OnImageCompressListener -import com.casic.electric.detector.model.ErrorMessageModel import com.casic.electric.detector.utils.FileType import com.casic.electric.detector.utils.LocaleConstant -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken +import com.google.gson.JsonParser import com.pengxh.kt.lite.extensions.createCompressImageDir import com.pengxh.kt.lite.utils.SaveKeyValues -import org.json.JSONObject import top.zibin.luban.Luban import top.zibin.luban.OnCompressListener import java.io.File @@ -18,18 +15,22 @@ /** * String扩展方法 */ -fun String.separateResponseState(): Boolean { +fun String.getResponseState(): Boolean { if (this.isBlank()) { return false } - return JSONObject(this).getBoolean("success") + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("success").asBoolean } -fun String.toErrorMessage(): String { - val errorModel = Gson().fromJson( - this, object : TypeToken() {}.type - ) - return errorModel.message.toString() +fun String.getResponseMessage(): String { + if (this.isBlank()) { + return "" + } + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("message").asString } /** @@ -131,4 +132,9 @@ } else { "6" } +} + +fun String.isNumber(): Boolean { + val regex = Regex("[-+]?\\d+(\\.\\d+)?") + return this.matches(regex) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt new file mode 100644 index 0000000..8b78a3c --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt @@ -0,0 +1,31 @@ +package com.casic.electric.detector.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import androidx.fragment.app.Fragment +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} + +fun ViewGroup.initImmersionBar(fragment: Fragment, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(fragment) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(fragment.requireContext())) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = fragment.requireContext().getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt new file mode 100644 index 0000000..84c9cd9 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt @@ -0,0 +1,3 @@ +package com.casic.electric.detector.model + +data class CalculateResult(val angle: Int, val direction: String, val distance: Int) diff --git a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java b/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java deleted file mode 100644 index 1574393..0000000 --- a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.casic.electric.detector.model; - -public class ErrorMessageModel { - private int code; - private String data; - private String exceptionClazz; - private String message; - private boolean isSuccess; - - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public String getExceptionClazz() { - return exceptionClazz; - } - - public void setExceptionClazz(String exceptionClazz) { - this.exceptionClazz = exceptionClazz; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public boolean isSuccess() { - return isSuccess; - } - - public void setSuccess(boolean success) { - isSuccess = success; - } -} diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt index 950fb91..f590226 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt @@ -90,10 +90,25 @@ /** * 上传工单中标识器信息 + * info中的主键 */ @GET("/ems/rs/task/update-task-mark") suspend fun uploadMarker( - @Query("userName") userId: String, - @Query("taskDetailId") taskId: String, + @Query("taskDetailId") taskId: String ): String + + /** + * 新建自由巡检任务 + * */ + @GET("ems/rs/task/addAppTask") + suspend fun createFreeTask( + @Query("patrollerId") patrollerId: String, + @Query("description") description: String + ): String + + /** + * 上传自由巡检过程中发现的标识器 + * */ + @POST("ems/event/uploadAppMarker.do") + suspend fun uploadTaskMarker(@Body requestBody: RequestBody): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt index 6834fc5..7836b28 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt @@ -1,5 +1,6 @@ package com.casic.electric.detector.retrofit +import com.casic.electric.detector.extensions.reformat import com.casic.electric.detector.utils.LabelDataClass import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.SmallLabelDataClass @@ -15,43 +16,32 @@ object RetrofitServiceManager { + private fun createApi(): RetrofitService { + val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String + val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String + val httpConfig = "http://${serverIp}:${serverPort}" + return RetrofitFactory.createRetrofit(httpConfig) + } + /** * 登录 */ suspend fun login(account: String, password: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.login(account, password) + return createApi().login(account, password) } /** * 更新版本 * */ suspend fun getApplicationVersion(): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getApplicationVersion() + return createApi().getApplicationVersion() } /** * 获取标识器信息文件 */ suspend fun getMarkerFile(userId: String, companyId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getMarkerFile(userId, companyId) + return createApi().getMarkerFile(userId, companyId) } /** @@ -64,39 +54,21 @@ "application/json;charset=UTF-8".toMediaType() ) - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getLabelPicture(requestBody) + return createApi().getLabelPicture(requestBody) } /** * 获取巡检工单 */ suspend fun getTask(userName: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getTask(userName) + return createApi().getTask(userName) } /** * 提交工单 */ suspend fun uploadTask(userId: String, taskId: String?, state: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadTask(userId, taskId.toString(), state) + return createApi().uploadTask(userId, taskId.toString(), state) } /** @@ -164,27 +136,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installLabel(res, multiParts[0], multiParts[1], null) + createApi().installLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installLabel(res, multiParts[0], null, null) + createApi().installLabel(res, multiParts[0], null, null) } else -> { - api.installLabel(res, null, null, null) + createApi().installLabel(res, null, null, null) } } } @@ -230,27 +196,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], null) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installSmallLabel(res, multiParts[0], null, null) + createApi().installSmallLabel(res, multiParts[0], null, null) } else -> { - api.installSmallLabel(res, null, null, null) + createApi().installSmallLabel(res, null, null, null) } } } @@ -279,27 +239,23 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2]) + createApi().uploadEvent( + taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2] + ) } 2 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) } 1 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) } else -> { - api.uploadEvent(taskIdMap, eventMap, null, null, null) + createApi().uploadEvent(taskIdMap, eventMap, null, null, null) } } } @@ -307,13 +263,27 @@ /** * 上传工单中标识器信息 */ - suspend fun uploadMarker(userName: String, taskDetailId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadMarker(userName, taskDetailId) + suspend fun uploadMarker(taskDetailId: String): String { + return createApi().uploadMarker(taskDetailId) + } + + /** + * 上传工单中标识器信息 + */ + suspend fun createFreeTask(patrollerId: String, description: String): String { + return createApi().createFreeTask(patrollerId, description) + } + + /** + * 上传自由巡检过程中发现的标识器 + */ + suspend fun uploadTaskMarker(taskId: String, models: ArrayList): String { + val param = JsonObject() + param.addProperty("taskId", taskId) + param.addProperty("ids", models.reformat()) + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return createApi().uploadTaskMarker(requestBody) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java index 4aba809..45d5a2f 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java +++ b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java @@ -1,8 +1,10 @@ package com.casic.electric.detector.utils; -public class GpioManager { +import android.util.Log; +public class GpioManager { + private static final String TAG = "GpioManager"; private static final int MT6761 = 0; private int selected; private final MT6761Gpio mt6761; @@ -38,6 +40,7 @@ * 璁剧疆GPIO杈撳嚭楂� * *********************************************************************/ public void setGpioHigh(String gpio) { + Log.d(TAG, "setGpioHigh: 调高电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioHigh(); @@ -48,6 +51,7 @@ * 璁剧疆GPIO杈撳嚭浣� * *********************************************************************/ public void setGpioLow(String gpio) { + Log.d(TAG, "setGpioLow: 调低电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioLow(); diff --git a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt deleted file mode 100644 index c589c4b..0000000 --- a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.electric.detector.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt index 4de12f2..9356f9a 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt @@ -13,7 +13,7 @@ ) const val PERMISSIONS_CODE = 999 - const val RADIUS_SIZE = 100f //相距多少米才聚合,单位:米 + const val RADIUS_SIZE = 100 //相距多少米才聚合,单位:米 const val AUTO_SAVE = "AUTO_SAVE" const val USER_ACCOUNT = "USER_ACCOUNT" @@ -28,10 +28,21 @@ const val APP_AUTHORITY = "com.casic.electric.detector.fileprovider" val POPUP_TITLES = arrayOf("更新数据", "下载工单", "关于软件", "事件上报", "标识器补全") - var CONDITION_ARRAY = arrayOf("种类", "编号", "名称", "所属区域", "所属道路", "运检单位", "责任人", "建设时间", "标识器ID") + var CONDITION_ARRAY = arrayOf( + "种类", + "编号", + "名称", + "所属区域", + "所属道路", + "运检单位", + "责任人", + "建设时间", + "标识器ID" + ) var CONTENT_ARRAY = arrayOf("电缆井", "电缆通道", "配电房", "开关站", "台区", "杆塔") var OBJECT_MODE_ARRAY = arrayOf("直线井", "转弯井", "丁字井", "十字井", "其他") - var WELL_COVER_MATERIAL_ARRAY_1 = arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") + var WELL_COVER_MATERIAL_ARRAY_1 = + arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") var WELL_COVER_MATERIAL_ARRAY_2 = arrayOf("水泥杆", "钢管杆", "铁塔", "其他") var CABINET_TYPE_ARRAY = arrayOf("无", "SM6", "SAFE", "RM6", "XGN15", "固体柜") var PIPE_MATERIAL_ARRAY = arrayOf("无", "PVC管", "波纹管", "镀锌钢管") @@ -42,7 +53,16 @@ var CROSS_PIPE_STATE_ARRAY = booleanArrayOf(false, false, false, false, false, false, false) var POINT_TYPE_ARRAY = arrayOf("管线", "管线附属物", "管线特征管点", "交叉穿越点") - var SPINNER_ARRAY = arrayOf("标识器ID", "所属区域", "所属线路", "所属道路", "权属单位", "安装部门", "安装时间", "备注") + var SPINNER_ARRAY = arrayOf( + "标识器ID", + "所属区域", + "所属线路", + "所属道路", + "权属单位", + "安装部门", + "安装时间", + "备注" + ) var DOWN_PIPE_TYPE_ARRAY = arrayOf("热力", "燃气", "供水", "电力", "通信") var BURY_METHOD_ARRAY = arrayOf("直埋", "圆管", "管块", "管沟", "架空") var COLOR_ARRAY = arrayOf("蓝色", "橙色", "红色", "黑色", "紫色", "黄色", "绿色") diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt index 4f0f2c7..61e55f6 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt @@ -14,14 +14,16 @@ import com.casic.electric.detector.callback.IAddressListener import com.casic.electric.detector.callback.ILocationListener -object LocationHub { - private const val kTag = "LocationHub" +class LocationHub constructor(context: Context) { - fun getCurrentLocation(context: Context, listener: ILocationListener) { - val locationClient = AMapLocationClient(context) + private val kTag = "LocationHub" + private val locationClient by lazy { AMapLocationClient(context) } + private val codeSearch by lazy { GeocodeSearch(context) } + + fun getCurrentLocation(isOnceLocation: Boolean, listener: ILocationListener) { val locationOption = AMapLocationClientOption() locationOption.locationMode = AMapLocationClientOption.AMapLocationMode.Hight_Accuracy - locationOption.isOnceLocation = true + locationOption.isOnceLocation = isOnceLocation locationClient.setLocationOption(locationOption) locationClient.setLocationListener { if (it.errorCode == 0) { @@ -36,9 +38,8 @@ locationClient.startLocation() } - fun antiCodingLocation(context: Context, location: Location, listener: IAddressListener) { + fun antiCodingLocation(location: Location, listener: IAddressListener) { try { - val codeSearch = GeocodeSearch(context) // 第一个参数表示一个LatLonPoint,第二参数表示范围多少米,第三个参数表示是火系坐标系还是GPS原生坐标系 val query = RegeocodeQuery( LatLonPoint(location.latitude, location.longitude), 10f, GeocodeSearch.AMAP @@ -55,4 +56,8 @@ e.printStackTrace() } } + + fun stopLocation() { + locationClient.stopLocation() + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt b/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt index aa1bdeb..e3d3289 100644 --- a/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt @@ -1,7 +1,6 @@ package com.casic.electric.detector.view import android.content.Context -import android.graphics.Color import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -12,10 +11,10 @@ import com.bumptech.glide.Glide import com.casic.electric.detector.R import com.casic.electric.detector.databinding.ActivityBigImageBinding +import com.casic.electric.detector.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class BigImageActivity : KotlinBaseActivity() { @@ -24,20 +23,12 @@ } override fun setupTopBarLayout() { - ImmerseStatusBarUtil.setColor(this, Color.BLACK) + binding.rootView.initImmersionBar(this, false, R.color.black) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - val index: Int = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return @@ -62,6 +53,14 @@ }) } + override fun observeRequestState() { + + } + + override fun initEvent() { + + } + inner class BigImageAdapter( private val context: Context, private val data: ArrayList ) : PagerAdapter() { diff --git a/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt b/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt index d3a89ca..6510104 100644 --- a/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt @@ -29,15 +29,15 @@ import com.casic.electric.detector.extensions.* import com.casic.electric.detector.utils.* import com.casic.electric.detector.vm.TaskViewModel -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia import com.luck.picture.lib.interfaces.OnResultCallbackListener import com.pengxh.kt.lite.extensions.* +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -53,7 +53,8 @@ private val context: Context = this@InstallLabelActivity private val gpioManager by lazy { GpioManager() } private val calendar by lazy { Calendar.getInstance() } - private val realPaths: ArrayList = ArrayList() //真实图片路径 + private val locationHub by lazy { LocationHub(this) } + private val realPaths = ArrayList() //真实图片路径 private var soundResId = 0 private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var soundPool: SoundPool @@ -67,12 +68,6 @@ override fun setupTopBarLayout() { binding.titleInclude.titleView.text = "安装新标识器" binding.titleInclude.titleView.setTextColor(R.color.themeColor.convertColor(this)) - - ImmersionBar.with(this) - .statusBarDarkFont(true) - .statusBarColor(R.color.mainBackground) - .init() - initLayoutImmersionBar(binding.rootView) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -126,7 +121,7 @@ binding.markerAttrInclude.remarkView3.setText("remarkView3".getDefaultValue()) //初始化图片九宫格 - imageAdapter = EditableImageAdapter(this, 3, 3f) + imageAdapter = EditableImageAdapter(this, 3, 3) binding.cameraInclude.addImageRecyclerView.adapter = imageAdapter taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] @@ -332,7 +327,7 @@ binding.markerAttrInclude.installTimeView.text = System.currentTimeMillis().timestampToCompleteDate() - LocationHub.getCurrentLocation(this, object : ILocationListener { + locationHub.getCurrentLocation(true, object : ILocationListener { override fun onAMapLocationGet(location: AMapLocation?) { if (location != null) { binding.markerAttrInclude.lngView.text = location.longitude.toString() @@ -518,8 +513,8 @@ weakReferenceHandler.postDelayed({ try { // 发送读标识器或搜索信号 - outputStream?.write("2".toByteArray()) - outputStream?.flush() + out.write("2".toByteArray()) + out.flush() } catch (e: IOException) { e.printStackTrace() } @@ -527,7 +522,7 @@ } } - override fun onDataReceived(buffer: ByteArray?, size: Int) { + override fun onDataReceived(buffer: ByteArray) { Log.d(kTag, "onDataReceived => " + buffer.contentToString()) if (buffer != null) { val message = weakReferenceHandler.obtainMessage() diff --git a/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt b/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt index 5bc2ac8..286bf4a 100644 --- a/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt @@ -24,7 +24,6 @@ import com.casic.electric.detector.extensions.* import com.casic.electric.detector.utils.* import com.casic.electric.detector.vm.TaskViewModel -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -33,9 +32,10 @@ import com.pengxh.kt.lite.extensions.isNetworkConnected import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -65,12 +65,6 @@ override fun setupTopBarLayout() { binding.titleInclude.titleView.text = "安装新电子标签" binding.titleInclude.titleView.setTextColor(R.color.themeColor.convertColor(this)) - - ImmersionBar.with(this) - .statusBarDarkFont(true) - .statusBarColor(R.color.mainBackground) - .init() - initLayoutImmersionBar(binding.rootView) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -103,7 +97,7 @@ binding.objectAttrInclude.objectRemarkView3.setText("objectRemarkView3".getDefaultValue()) //初始化图片九宫格 - imageAdapter = EditableImageAdapter(this, 3, 3f) + imageAdapter = EditableImageAdapter(this, 3, 3) binding.cameraInclude.addImageRecyclerView.adapter = imageAdapter taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] @@ -308,8 +302,8 @@ weakReferenceHandler.postDelayed({ try { // 发送读标识器或搜索信号 - outputStream?.write("2".toByteArray()) - outputStream?.flush() + out.write("2".toByteArray()) + out.flush() } catch (e: IOException) { e.printStackTrace() } @@ -317,7 +311,7 @@ } } - override fun onDataReceived(buffer: ByteArray?, size: Int) { + override fun onDataReceived(buffer: ByteArray) { if (buffer != null) { val message = weakReferenceHandler.obtainMessage() message.what = 2023081702 diff --git a/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt b/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt index 44d56ef..9c98b5f 100644 --- a/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt @@ -1,36 +1,29 @@ package com.casic.electric.detector.view import android.os.Bundle -import android.util.Log import androidx.lifecycle.ViewModelProvider import com.amap.api.navi.NaviSetting import com.casic.electric.detector.databinding.ActivityLoginBinding -import com.casic.electric.detector.extensions.initLayoutImmersionBar -import com.casic.electric.detector.utils.GpioManager -import com.casic.electric.detector.utils.LoadingDialogHub import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.vm.UserViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.getScreenHeight -import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog class LoginActivity : KotlinBaseActivity() { private val kTag = "LoginActivity" private lateinit var userViewModel: UserViewModel - private val gpioManager by lazy { GpioManager() } override fun initViewBinding(): ActivityLoginBinding { return ActivityLoginBinding.inflate(layoutInflater) } override fun initOnCreate(savedInstanceState: Bundle?) { - gpioManager.setGpioLow("18") //先把导航隐私政策声明,后面导航会用到 NaviSetting.updatePrivacyShow(this, true, true) NaviSetting.updatePrivacyAgree(this, true) @@ -60,11 +53,8 @@ val serversIp = binding.serversIpView.text.toString() val serversPort = binding.serversPortView.text.toString() if (account.isBlank() || password.isBlank() || serversIp.isBlank() || serversPort.isBlank()) { - AlertMessageDialog.Builder() - .setContext(this) - .setTitle("账号登录") - .setMessage("信息不能为空哦!") - .setPositiveButton("知道了") + AlertMessageDialog.Builder().setContext(this).setTitle("账号登录") + .setMessage("信息不能为空哦!").setPositiveButton("知道了") .setOnDialogButtonClickListener(object : AlertMessageDialog.OnDialogButtonClickListener { override fun onConfirmClick() { @@ -102,9 +92,6 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(true).init() - initLayoutImmersionBar(binding.rootView) - - Log.d(kTag, "setupTopBarLayout => [${getScreenWidth()}, ${getScreenHeight()}]") } override fun onResume() { diff --git a/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt b/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt index 36a8d55..a0a4aac 100644 --- a/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt @@ -1,15 +1,21 @@ package com.casic.electric.detector.view +import android.annotation.SuppressLint import android.app.AlertDialog +import android.app.Dialog import android.content.Context -import android.content.Intent import android.graphics.Color import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable +import android.media.AudioAttributes +import android.media.SoundPool import android.os.Bundle -import android.os.PowerManager -import android.provider.Settings +import android.os.CountDownTimer +import android.util.Log import android.view.KeyEvent +import android.view.View +import android.view.animation.Animation +import android.view.animation.RotateAnimation import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import com.amap.api.location.AMapLocation @@ -21,6 +27,8 @@ import com.amap.api.maps.model.LatLngBounds import com.amap.api.maps.model.MyLocationStyle import com.casic.electric.detector.R +import com.casic.electric.detector.adapter.EditableImageAdapter +import com.casic.electric.detector.base.SerialPortActivity import com.casic.electric.detector.bean.LabelBean import com.casic.electric.detector.bean.SmallLabelBean import com.casic.electric.detector.bean.TaskBean @@ -29,83 +37,109 @@ import com.casic.electric.detector.cluster.ClusterOverlay import com.casic.electric.detector.cluster.RegionItem import com.casic.electric.detector.databinding.ActivityMainBinding +import com.casic.electric.detector.databinding.DialogInstallMarkerBinding +import com.casic.electric.detector.databinding.DialogInstallSmallMarkerBinding +import com.casic.electric.detector.databinding.DialogSearchMarkerBinding import com.casic.electric.detector.extensions.appendExcelDownloadUrl import com.casic.electric.detector.extensions.drawCircle -import com.casic.electric.detector.extensions.initLayoutImmersionBar +import com.casic.electric.detector.extensions.hexToString +import com.casic.electric.detector.extensions.initImmersionBar +import com.casic.electric.detector.extensions.isNumber +import com.casic.electric.detector.extensions.toHex import com.casic.electric.detector.utils.DataBaseManager import com.casic.electric.detector.utils.ExcelHub -import com.casic.electric.detector.utils.LoadingDialogHub +import com.casic.electric.detector.utils.GpioManager import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.LocationHub import com.casic.electric.detector.utils.RouteOnMap import com.casic.electric.detector.vm.TaskViewModel import com.casic.electric.detector.widgets.QueryMarkerDialog import com.casic.electric.detector.widgets.SamplePopupWindow -import com.gyf.immersionbar.ImmersionBar -import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.callback.OnDownloadListener +import com.google.gson.Gson +import com.pengxh.kt.lite.extensions.binding import com.pengxh.kt.lite.extensions.createDownloadFileDir -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.dp2px +import com.pengxh.kt.lite.extensions.initDialogLayoutParams import com.pengxh.kt.lite.extensions.isNetworkConnected import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.toJson +import com.pengxh.kt.lite.utils.FileDownloadManager +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog +import com.pengxh.kt.lite.widget.dialog.AlertInputDialog +import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File +import java.text.DecimalFormat +import java.util.Calendar +import java.util.Timer +import java.util.TimerTask -class MainActivity : KotlinBaseActivity() { +@SuppressLint("all") +class MainActivity : SerialPortActivity() { private val kTag = "MainActivity" - private val context: Context = this@MainActivity + private val context = this@MainActivity + private val gpioManager by lazy { GpioManager() } private val samplePopupWindow by lazy { SamplePopupWindow(this) } + private val gson by lazy { Gson() } + private val locationHub by lazy { LocationHub(this) } + private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } + private val backDrawables by lazy { HashMap() } + private val installMarkerDialog by lazy { InstallMarkerDialog(this) } + private val installSmallMarkerDialog by lazy { InstallSmallMarkerDialog(this) } + private val searchDialog by lazy { SearchMarkerDialog(this) } private var clickTime: Long = 0 - private lateinit var wakeLock: PowerManager.WakeLock - private lateinit var aMap: AMap - private lateinit var taskViewModel: TaskViewModel - private lateinit var taskBean: TaskBean - private var latitude: Double = 0.0 - private var longitude: Double = 0.0 private var labels = ArrayList() private var smallLabels = ArrayList() private var clusterOverlay: ClusterOverlay? = null - private val backDrawables = HashMap() - private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } + private var latitude: Double = 0.0 + private var longitude: Double = 0.0 + private var isFreeTask = false + private var ids = ArrayList() + private var signalTask: TimerTask? = null + private var searchMarkerTimer: Timer? = null + private lateinit var aMap: AMap + private lateinit var taskBean: TaskBean + private lateinit var taskId: String + + /***inner class 需要用到*****start*/ + private val taskViewModel by lazy { ViewModelProvider(this)[TaskViewModel::class.java] } + 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 var soundResourceId = 0 + private var slowSoundResourceId = 0 + private var fastSoundResourceId = 0 + + /***inner class 需要用到*****end*/ override fun initViewBinding(): ActivityMainBinding { return ActivityMainBinding.inflate(layoutInflater) } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).statusBarColor(R.color.themeColor).init() - initLayoutImmersionBar(binding.rootView) - } - - override fun observeRequestState() { - + binding.rootView.initImmersionBar(this, false, R.color.themeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { - val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager - wakeLock = powerManager.run { - newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this@MainActivity.localClassName).apply { - acquire(60 * 60 * 1000L) - } - } + soundResourceId = soundPool.load(this, R.raw.ring3, 1) + slowSoundResourceId = soundPool.load(this, R.raw.ring4, 1) + fastSoundResourceId = soundPool.load(this, R.raw.ring2, 1) + //地图初始化 initMapConfig(savedInstanceState) samplePopupWindow.setPopupMenuItem(LocaleConstant.POPUP_TITLES) samplePopupWindow.setBackgroundDrawable(null) - taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] + //task网络请求监听 taskViewModel.markerFileResult.observe(this) { if (it.success == "true") { //清空之前的数据 @@ -122,11 +156,13 @@ val smallLabelDownloadUrl = urlArray[1].appendExcelDownloadUrl() //下载标识器 - labelDownloadUrl.downloadFile( - createDownloadFileDir().toString(), object : OnDownloadListener { - override fun onDownloadEnd(file: File?) { + FileDownloadManager.Builder().setDownloadFileSource(labelDownloadUrl) + .setFileSuffix("xls").setFileSaveDirectory(createDownloadFileDir()) + .setOnFileDownloadListener(object : + FileDownloadManager.OnFileDownloadListener { + override fun onDownloadEnd(file: File) { lifecycleScope.launch { - labels = ExcelHub.readLabel(file?.absolutePath) + labels = ExcelHub.readLabel(file.absolutePath) withContext(Dispatchers.IO) { labels.forEach { label -> DataBaseManager.get.insertLabel(label) @@ -137,21 +173,23 @@ } } - override fun onDownloadStart(totalBytes: Long) { + override fun onFailure(throwable: Throwable) { } - override fun onProgressChanged(currentBytes: Long) { + override fun onProgressChanged(progress: Int) { } - }) + }).build().start() //下载附属标识器 - smallLabelDownloadUrl.downloadFile( - createDownloadFileDir().toString(), object : OnDownloadListener { - override fun onDownloadEnd(file: File?) { + FileDownloadManager.Builder().setDownloadFileSource(smallLabelDownloadUrl) + .setFileSuffix("xls").setFileSaveDirectory(createDownloadFileDir()) + .setOnFileDownloadListener(object : + FileDownloadManager.OnFileDownloadListener { + override fun onDownloadEnd(file: File) { lifecycleScope.launch { - smallLabels = ExcelHub.readSmallLabel(file?.absolutePath) + smallLabels = ExcelHub.readSmallLabel(file.absolutePath) withContext(Dispatchers.IO) { smallLabels.forEach { label -> DataBaseManager.get.insertSmallLabel(label) @@ -160,14 +198,14 @@ } } - override fun onDownloadStart(totalBytes: Long) { + override fun onFailure(throwable: Throwable) { } - override fun onProgressChanged(currentBytes: Long) { + override fun onProgressChanged(progress: Int) { } - }) + }).build().start() } } } @@ -175,11 +213,8 @@ // if (it.success == "true") { // //清空之前的数据 // DataBaseManager.get.clearTasks() -// AlertMessageDialog.Builder() -// .setContext(this) -// .setTitle("温馨提示") -// .setMessage("您有${it.message.size}个新任务!") -// .setPositiveButton("知道了") +// AlertMessageDialog.Builder().setContext(this).setTitle("温馨提示") +// .setMessage("您有${it.message.size}个新任务!").setPositiveButton("知道了") // .setOnDialogButtonClickListener(object : // AlertMessageDialog.OnDialogButtonClickListener { // override fun onConfirmClick() { @@ -188,19 +223,24 @@ // }).build().show() // } // } + taskViewModel.freeTaskResult.observe(this) { taskId = it } + taskViewModel.uploadTaskMarkerResult.observe(this) { + "自由巡检任务已完成".show(this) + ids.clear() + } } override fun initEvent() { binding.rightImageView.setOnClickListener { - CoroutineScope(Dispatchers.Main).launch { + lifecycleScope.launch(Dispatchers.Main) { val labels = withContext(Dispatchers.IO) { DataBaseManager.get.queryLabelById("0") } if (labels.isNotEmpty()) { samplePopupWindow.setShowPosition(4) } - val x = binding.rightImageView.width - samplePopupWindow.width - 1f.dp2px(context) - samplePopupWindow.showAsDropDown(binding.rightImageView, x, 1f.dp2px(context)) + val x = binding.rightImageView.width - samplePopupWindow.width - 1.dp2px(context) + samplePopupWindow.showAsDropDown(binding.rightImageView, x, 1.dp2px(context)) } } @@ -219,35 +259,33 @@ //安装。上传,然后存入本地库 binding.installButton.setOnClickListener { - AlertControlDialog.Builder() - .setContext(context) - .setTitle("提示") - .setMessage("请选择安装对象") - .setPositiveButton("标识器") - .setNegativeButton("电子标签") - .setOnDialogButtonClickListener(object : + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("请选择安装对象").setPositiveButton("标识器") + .setNegativeButton("电子标签").setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { //标识器 - navigatePageTo() + /** + * 改为Dialog方式,避免频繁打开/关闭串口 + * */ + installMarkerDialog.show() } override fun onCancelClick() { //电子标签 - navigatePageTo() + /** + * 改为Dialog方式,避免频繁打开/关闭串口 + * */ + installSmallMarkerDialog.show() } }).build().show() } //查看 binding.viewButton.setOnClickListener { - QueryMarkerDialog.Builder() - .setContext(this) - .setTitle("查看标识器") - .setConditionArray(LocaleConstant.CONDITION_ARRAY) - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : + QueryMarkerDialog.Builder().setContext(this).setTitle("查看标识器") + .setConditionArray(LocaleConstant.CONDITION_ARRAY).setNegativeButton("取消") + .setPositiveButton("确定").setOnDialogButtonClickListener(object : QueryMarkerDialog.OnDialogButtonClickListener { override fun onConfirmClick( selectedCondition: String, vararg contentValue: String @@ -310,30 +348,25 @@ // arrayList.add("任务${index + 1}:${taskBean.taskId},${taskBean.desc}") // } // -// BottomActionSheet.Builder() -// .setContext(this) -// .setItemTextColor(Color.BLUE) +// BottomActionSheet.Builder().setContext(this).setItemTextColor(Color.BLUE) // .setActionItemTitle(arrayList) // .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { // override fun onActionItemClick(position: Int) { // val taskBean = task[position] // SaveKeyValues.putValue(LocaleConstant.TASK_ID, taskBean.taskId) -// AlertControlDialog.Builder() -// .setContext(context) -// .setTitle("提示") -// .setMessage("请选择操作方式") -// .setPositiveButton("执行工单") +// AlertControlDialog.Builder().setContext(context).setTitle("提示") +// .setMessage("请选择操作方式").setPositiveButton("执行工单") // .setNegativeButton("提交工单") // .setOnDialogButtonClickListener(object : // AlertControlDialog.OnDialogButtonClickListener { // override fun onConfirmClick() { // detectRedrawGraphic(taskBean.taskId) +// +// val latLng = LatLng( +// taskBean.lat.toDouble(), taskBean.lng.toDouble() +// ) // aMap.moveCamera( -// CameraUpdateFactory.newLatLngZoom( -// LatLng( -// taskBean.lat.toDouble(), taskBean.lng.toDouble() -// ), 15f -// ) +// CameraUpdateFactory.newLatLngZoom(latLng, 16f) // ) // uploadTask(taskBean.taskId, "1") // } @@ -345,15 +378,12 @@ // } // }).build().show() // } else { -// AlertMessageDialog.Builder() -// .setContext(this) -// .setTitle("温馨提示") -// .setMessage("现有任务已完成,请点击右上角菜单按钮下载新工单!") -// .setPositiveButton("知道了") -// .setOnDialogButtonClickListener(object : +// AlertMessageDialog.Builder().setContext(this).setTitle("温馨提示") +// .setMessage("现有任务已完成,请点击右上角菜单下载新工单或者开始自由巡检") +// .setPositiveButton("知道了").setOnDialogButtonClickListener(object : // AlertMessageDialog.OnDialogButtonClickListener { // override fun onConfirmClick() { -// +// startFreeTask() // } // }).build().show() // } @@ -361,7 +391,118 @@ //探测 binding.detectionButton.setOnClickListener { -// navigatePageTo() + /** + * 改为Dialog方式,避免频繁打开/关闭串口 + * */ + searchDialog.show() + } + + //自由巡检 + binding.stopFreeTaskButton.setOnLongClickListener { + AlertMessageDialog.Builder().setContext(this).setTitle("温馨提示") + .setMessage("是否确定结束此次自由巡检任务?").setPositiveButton("是") + .setOnDialogButtonClickListener(object : + AlertMessageDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + isFreeTask = false + soundPool.autoPause() + + //降低串口电位 + gpioManager.setGpioLow("18") + + taskViewModel.uploadTaskMarker(taskId, ids) + binding.stopFreeTaskButton.visibility = View.GONE + } + }).build().show() + true + } + } + + private fun startFreeTask() { + AlertInputDialog.Builder().setContext(this).setTitle("新建自由巡检任务") + .setHintMessage("请输入自由巡检任务简要描述").setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : AlertInputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String + taskViewModel.createFreeTask(userId, value) + + //调高串口电位 + gpioManager.setGpioHigh("18") + + soundPool.play(soundResourceId, 1f, 1f, 0, -1, 1f) + isFreeTask = true + //自由巡检 + signalTask = object : TimerTask() { + override fun run() { + out.write('2'.code) + out.flush() + } + } + searchMarkerTimer = Timer() + searchMarkerTimer?.apply { + schedule(signalTask, 0, 100) + } + + binding.stopFreeTaskButton.visibility = View.VISIBLE + } + + override fun onCancelClick() {} + }).build().show() + } + + override fun onDataReceived(buffer: ByteArray) { + val hex = buffer.toHex() + Log.d(kTag, "$kTag => $hex") + if (searchDialog.isDetectMarker) { + searchDialog.bindingValue(hex) +// } else if (installMarkerDialog.isReadMarker) { +// val markerId = hex.take(20).hexToString() +// if (markerId.isNumber()) { +// installMarkerDialog.bindingValue(markerId) +// } +// } else if (installSmallMarkerDialog.isReadMarker) { +// val markerId = hex.take(20).hexToString() +// if (markerId.isNumber()) { +// installSmallMarkerDialog.bindingValue(markerId) +// } + } else if (isFreeTask) { + val markerId = hex.take(20).hexToString() + if (markerId.isNumber()) { + "标识器${markerId}已探测".show(this) + ids.add(markerId) + } + } + } + + override fun observeRequestState() { + taskViewModel.loadState.observe(this) { + when (it) { + LoadState.Loading -> { + if (installMarkerDialog.isInstallMarker || installSmallMarkerDialog.isInstallMarker) { + LoadingDialogHub.show(this, "标识器安装中,请稍后...") + } else if (searchDialog.isDetectMarker) { + searchDialog.taskBean?.apply { + "标识器${this.markerId}已探测!".show(context) +// DataBaseManager.get.updateTaskLabel(this) + } + } else { + LoadingDialogHub.show(this, "提交工单中,请稍后") + } + } + + else -> { + if (installMarkerDialog.isInstallMarker) { + installMarkerDialog.dismiss() + installMarkerDialog.isInstallMarker = false + } else if (installSmallMarkerDialog.isInstallMarker) { + installSmallMarkerDialog.dismiss() + installSmallMarkerDialog.isInstallMarker = false + } + LoadingDialogHub.dismiss() + } + } + detectRedrawGraphic(taskBean.taskId) } } @@ -375,6 +516,7 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜 //显示定位小蓝点 val locationStyle = MyLocationStyle() locationStyle.interval(2000) @@ -387,7 +529,7 @@ longitude = it.longitude latitude = it.latitude //经纬度逆编码 - LocationHub.antiCodingLocation(context, it) { address -> + locationHub.antiCodingLocation(it) { address -> binding.currentLocationView.text = address } } @@ -417,7 +559,7 @@ } private fun moveToCurrentLocation() { - LocationHub.getCurrentLocation(this, object : ILocationListener { + locationHub.getCurrentLocation(true, object : ILocationListener { override fun onAMapLocationGet(location: AMapLocation?) { if (location != null) { aMap.moveCamera( @@ -432,46 +574,35 @@ }) } - //更新数据 - private fun updateLabels() { - AlertControlDialog.Builder() - .setContext(this) - .setTitle("提示") - .setMessage("是否更新数据?") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onConfirmClick() { - if (isNetworkConnected()) { - val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") - val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") - - LoadingDialogHub.show(this@MainActivity, "获取标识器信息中,请稍后") - //TODO 设计如此,都传companyId - taskViewModel.getMarkerFile(companyId.toString(), companyId.toString()) - } else { - NoNetworkDialog.Builder() - .setContext(context) - .setOnDialogButtonClickListener(object : - NoNetworkDialog.OnDialogButtonClickListener { - override fun onButtonClick() { - val intent = Intent(Settings.ACTION_SETTINGS) - startActivity(intent) - } - }).build().show() - } - } - - override fun onCancelClick() { - - } - }).build().show() - } +// private fun saveTaskInformation(it: TaskModel) { +// val userName = SaveKeyValues.getValue(LocaleConstant.USER_NAME, "") as String +// if (it.message.size > 0) { +// it.message.forEach { messageModel -> +// val count = DataBaseManager.get.countTaskById(messageModel.id.toString()) +// if (count == 0) { +// messageModel.taskDetailInfos.forEach { info -> +// DataBaseManager.get.insertTaskInformation( +// userName, +// messageModel.description, +// info.taskId.toString(), +// info.id.toString(), +// info.markerId.toString(), +// info.markerIdReal.toString(), +// info.longitude.toString(), +// info.latitude.toString(), +// messageModel.status +// ) +// } +// } +// } +// "工单下载成功!".show(context) +// } +// } private fun showLabelsOnMap() { clusterOverlay?.onDestroy() val clusterItems = ArrayList() + labels.forEach { val latLng = LatLng(it.latitude.toDouble(), it.longitude.toDouble(), false) val regionItem = RegionItem(latLng, it.markerId.toString()) @@ -480,7 +611,7 @@ clusterOverlay = ClusterOverlay(context, aMap, clusterItems, regionRadius) clusterOverlay?.setClusterRender { clusterNum -> - val radius = 80f.dp2px(context) + val radius = 80.dp2px(context) if (clusterNum == 0) { var bitmapDrawable = backDrawables[0] if (bitmapDrawable == null) { @@ -546,9 +677,7 @@ val latLngBounds = builder.build() aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 0)) - BottomActionSheet.Builder() - .setContext(this) - .setItemTextColor(Color.BLUE) + BottomActionSheet.Builder().setContext(this).setItemTextColor(Color.BLUE) .setActionItemTitle(listOf("标识器信息", "附属电子标签信息", "到这里去")) .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { override fun onActionItemClick(position: Int) { @@ -578,12 +707,7 @@ showElectricMarkers(electricMarkers) } - 2 -> { - RouteOnMap.startNavigation( - context, item.tag, - LatLng(item.position.latitude, item.position.longitude) - ) - } + 2 -> RouteOnMap.startNavigation(context, item.tag, latLng) } } }).build().show() @@ -591,14 +715,74 @@ } private fun showElectricMarkers(markers: ArrayList) { - AlertDialog.Builder(context) - .setIcon(R.mipmap.ic_launcher) - .setTitle("电子标签列表") + AlertDialog.Builder(context).setIcon(R.mipmap.ic_launcher).setTitle("电子标签列表") .setSingleChoiceItems(markers.toTypedArray(), -1) { _, which -> navigatePageTo(markers[which]) }.show() } + private fun detectRedrawGraphic(taskId: String) { +// val tasks = DataBaseManager.get.queryTaskById(taskId) +// if (tasks.isNotEmpty()) { +// tasks.forEach { +// val latLng = LatLng(it.lat.toDouble(), it.lng.toDouble()) +// val otMarkerOptions = MarkerOptions() +// otMarkerOptions.position(latLng) +// otMarkerOptions.visible(true) // 设置可见 +// if (it.state == "未开始") { +// otMarkerOptions.icon( +// BitmapDescriptorFactory.fromBitmap( +// BitmapFactory.decodeResource(resources, R.mipmap.label_red1) +// ) +// ).period(99).title("工单标识器").snippet(it.markerId) +// } else { +// otMarkerOptions.icon( +// BitmapDescriptorFactory.fromBitmap( +// BitmapFactory.decodeResource(resources, R.mipmap.label_blue1) +// ) +// ).period(99).title("工单标识器").snippet(it.markerId) +// } +// aMap.addMarker(otMarkerOptions) +// } +// } + showLabelsOnMap() + } + + private fun uploadTask(taskId: String?, state: String) { + if (isNetworkConnected()) { + val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String + taskViewModel.uploadTask(userId, taskId, state) + } else { + "网络连接已断开,请检查".show(this) + } + } + + //更新数据 + private fun updateLabels() { + AlertControlDialog.Builder().setContext(this).setTitle("提示").setMessage("是否更新数据?") + .setNegativeButton("取消").setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + if (isNetworkConnected()) { + val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") + + LoadingDialogHub.show(this@MainActivity, "获取标识器信息中,请稍后") + /** + * 后台设计如此,都传companyId + * */ + taskViewModel.getMarkerFile(companyId.toString(), companyId.toString()) + } else { + "网络连接已断开,请检查".show(context) + } + } + + override fun onCancelClick() { + + } + }).build().show() + } + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { return if (keyCode == KeyEvent.KEYCODE_BACK) { if (System.currentTimeMillis() - clickTime > 2000) { @@ -643,8 +827,270 @@ } override fun onDestroy() { - wakeLock.release() super.onDestroy() binding.mapView.onDestroy() + signalTask?.cancel() + searchMarkerTimer?.cancel() + soundPool.release() + locationHub.stopLocation() + //降低串口电位 + gpioManager.setGpioLow("18") + } + + /**安装标识器对话框******************************************************************************/ + inner class InstallMarkerDialog(context: Context) : Dialog(context) { + + private val binding: DialogInstallMarkerBinding by binding() + private val calendar by lazy { Calendar.getInstance() } + private val realPaths = ArrayList() //真实图片路径 + private lateinit var imageAdapter: EditableImageAdapter + + var isReadMarker = false + var isInstallMarker = false + } + + /**安装小标签对话框******************************************************************************/ + inner class InstallSmallMarkerDialog(context: Context) : Dialog(context) { + + private val binding: DialogInstallSmallMarkerBinding by binding() + private val calendar by lazy { Calendar.getInstance() } + private val realPaths = ArrayList() //真实图片路径 + private lateinit var imageAdapter: EditableImageAdapter + + var isReadMarker = false + var isInstallMarker = false + } + + /**探测标识器对话框******************************************************************************/ + inner class SearchMarkerDialog(context: Context) : Dialog(context) { + + private val binding: DialogSearchMarkerBinding by binding() + private val decimal by lazy { DecimalFormat("0.0") } + private val degreeCache by lazy { HashMap() } + private var isPlaying = false + private var markerId = "" + private lateinit var searchMarkerTimer: Timer + private lateinit var signalTask: TimerTask + private lateinit var energyTask: TimerTask + private lateinit var countDownTimer: CountDownTimer + + var isDetectMarker = false + var taskBean: TaskBean? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.initDialogLayoutParams(1f) + binding.depthButton.setOnClickListener { + signalTask.cancel() + energyTask.cancel() + searchMarkerTimer.cancel() + + out.write('3'.code) +// val result = DataBaseManager.get.queryLabelById(markerId) +// if (result.isNotEmpty()) { +// val tag = when (result.first().identifierType) { +// "EM30" -> '7' +// "EM50" -> '8' +// "EM14" -> '9' +// else -> '1' +// } +// if (tag == '1') { +// "此标识器无法读取埋深!".show(context) +// } else { +// // 发送读取标识器埋设深度指令 +// LoadingDialogHub.show(this@MainActivity, "正在测距,请稍后...") +// out.write(tag.code) +// out.flush() +// countDownTimer = object : CountDownTimer(15 * 1000, 1000) { +// override fun onTick(millisUntilFinished: Long) { +// +// } +// +// override fun onFinish() { +// LoadingDialogHub.dismiss() +// "探测此标识器深度超时,请重试".show(context) +// initTimer() +// } +// } +// countDownTimer.start() +// } +// } else { +// "标识器未安装,安装成功后才可读取埋深!".show(context) +// } + } + + binding.markerInfoButton.setOnClickListener { + //查库 + val result = DataBaseManager.get.queryLabelById(markerId) + if (result.isNotEmpty()) { +// context.navigatePageTo(result.first().toJson()) + } else { +// context.navigatePageTo(markerId) + } + } + } + + override fun onStart() { + super.onStart() + //调高串口电位 + gpioManager.setGpioHigh("18") + + initTimer() + + isDetectMarker = true + + //角度 + degreeCache["lastDegree"] = 0f + } + + fun bindingValue(hex: String) { + if (hex.startsWith("4E")) { + try { + //4E转为String为N,代表能量值 + //用能量值转动表盘 + val energyResponse = hex.take(10).hexToString() + val energy = energyResponse.substring(1).toInt() + if (energy >= 4000) { + isPlaying = if (!isPlaying) { + soundPool.play(fastSoundResourceId, 1f, 1f, 0, 0, 1f) + true + } else { + soundPool.pause(fastSoundResourceId) + false + } + } else { + isPlaying = if (!isPlaying) { + soundPool.play(slowSoundResourceId, 1f, 1f, 0, 0, 1f) + true + } else { + soundPool.pause(slowSoundResourceId) + false + } + } + + binding.resultTextView.text = "信号能量值:${energyResponse}" + + //转换为转动的角度 + val degree = (energy.toFloat() / (50 * 100)) * 180 + binding.energyValueView.text = decimal.format(degree) + + degreeCache["lastDegree"]?.apply { + val animation = RotateAnimation( + this, degree, + Animation.RELATIVE_TO_SELF, 0.5f, + Animation.RELATIVE_TO_SELF, 0.5f + ) + animation.duration = 0 + animation.fillAfter = true + binding.needleView.startAnimation(animation) + } + + //保存旋转后的角度 + degreeCache["lastDegree"] = degree + + if (energy <= 700) {//18° + binding.energyTipsView.text = "标识器信号较弱,可能距离较远" + binding.energyTipsView.setTextColor(Color.parseColor("#8D1717")) + binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_red) + + binding.depthButton.isEnabled = false + binding.depthButton.setTextColor(Color.parseColor("#CCCCCC")) + binding.depthButton.setBackgroundResource(R.mipmap.left_button_disable) + binding.markerInfoButton.isEnabled = false + binding.markerInfoButton.setTextColor(Color.parseColor("#CCCCCC")) + binding.markerInfoButton.setBackgroundResource(R.mipmap.right_button_disable) + + binding.searchResultView.text = "未检测到标识器" + binding.searchResultView.setTextColor(Color.parseColor("#8D1717")) + binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_red) + } else if (energy >= 4100) {//148° + binding.energyTipsView.text = "标识器信号极强,可能在正下方" + binding.energyTipsView.setTextColor(Color.parseColor("#428d00")) + binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_green) + } else {//[18°,148°] + binding.energyTipsView.text = "已靠近标识器,请继续移动位置" + binding.energyTipsView.setTextColor(Color.parseColor("#8C5700")) + binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_yellow) + } + } catch (e: NumberFormatException) { + e.printStackTrace() + } + } else if (hex.startsWith("53")) { + LoadingDialogHub.dismiss() + countDownTimer.cancel() + try { + val depthResponse = hex.take(10).hexToString() + val depth = depthResponse.drop(2).toInt() + AlertMessageDialog.Builder().setContext(context).setTitle("温馨提示") + .setMessage("标识器埋深:${depth}厘米").setPositiveButton("知道了") + .setOnDialogButtonClickListener(object : + AlertMessageDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + initTimer() + } + }).build().show() + } catch (e: NumberFormatException) { + e.printStackTrace() + } + } else { + val id = hex.take(20).hexToString() + if (id.isNumber()) { + markerId = id + + binding.depthButton.isEnabled = true + binding.depthButton.setTextColor(Color.WHITE) + binding.depthButton.setBackgroundResource(R.mipmap.left_button_enable) + binding.markerInfoButton.isEnabled = true + binding.markerInfoButton.setTextColor(Color.WHITE) + binding.markerInfoButton.setBackgroundResource(R.mipmap.right_button_enable) + + binding.searchResultView.text = "已检测到标识器" + binding.searchResultView.setTextColor(Color.parseColor("#428d00")) + binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_green) + + //自动上传标识器 +// taskBean = DataBaseManager.get.queryTaskLabelByIdAndState(markerId, "未开始") +// taskBean?.apply { +// /** +// * 此taskCode是 [com.casic.detector.model.TaskModel.MessageModel.TaskDetailInfosModel] 里面的主键,也就是这个标签在数据库里面的主键 +// * */ +// taskViewModel.uploadMarker(taskCode) +// } + } + } + } + + private fun initTimer() { + searchMarkerTimer = Timer() + + signalTask = object : TimerTask() { + override fun run() { + out.write('2'.code) + out.flush() + } + } + + energyTask = object : TimerTask() { + override fun run() { + out.write('6'.code) + out.flush() + } + } + + //错开信号和能量定时器 + searchMarkerTimer.schedule(signalTask, 0, 201) + searchMarkerTimer.schedule(energyTask, 0, 251) + } + + override fun dismiss() { + signalTask.cancel() + energyTask.cancel() + searchMarkerTimer.cancel() + //降低串口电位 + gpioManager.setGpioLow("18") + isDetectMarker = false + soundPool.autoPause() + super.dismiss() + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt b/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt index 6a00429..cbd6137 100644 --- a/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt @@ -13,18 +13,16 @@ import com.casic.electric.detector.R import com.casic.electric.detector.databinding.ActivityVersionControlBinding import com.casic.electric.detector.extensions.appendDownloadUrl -import com.casic.electric.detector.extensions.initLayoutImmersionBar +import com.casic.electric.detector.extensions.initImmersionBar import com.casic.electric.detector.utils.FileType -import com.casic.electric.detector.utils.LoadingDialogHub import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.vm.VersionViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.createDownloadFileDir -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.FileDownloadManager +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import java.io.File @@ -90,8 +88,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(true).init() - initLayoutImmersionBar(binding.rootView) + binding.rootView.initImmersionBar(this, true, R.color.white) binding.titleInclude.titleView.visibility = View.GONE } @@ -108,22 +105,26 @@ val downloadPath = url!!.appendDownloadUrl(FileType.APK) Log.d(kTag, "downloadApk => $downloadPath") //开始下载 - downloadPath.downloadFile(createDownloadFileDir().toString(), object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() - } + FileDownloadManager.Builder() + .setDownloadFileSource(downloadPath) + .setFileSuffix("apk") + .setFileSaveDirectory(createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadEnd(file: File) { + progressDialog.dismiss() + progressDialog.progress = 0 + //安装APK + installApk(file) + } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } + override fun onFailure(throwable: Throwable) { - override fun onDownloadEnd(file: File?) { - progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK - installApk(file) - } - }) + } + + override fun onProgressChanged(progress: Int) { + progressDialog.progress = progress + } + }).build().start() } private fun installApk(apkPackage: File?) { diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt b/app/src/main/java/com/casic/electric/detector/extensions/Context.kt deleted file mode 100644 index fcf36a7..0000000 --- a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.casic.electric.detector.extensions - -import android.content.Context -import android.view.ViewGroup -import com.pengxh.kt.lite.extensions.getStatusBarHeight - -/** - * 设置沉浸式状态栏,兼容Android 11+ - * */ -fun Context.initLayoutImmersionBar(rootView: ViewGroup) { - rootView.setPadding(0, this.getStatusBarHeight(), 0, 0) - rootView.requestLayout() -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt index 6e08b27..e98408a 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt @@ -13,12 +13,4 @@ paint.color = color canvas.drawArc(rectF, 0f, 360f, true, paint) return bitmap -} - -fun Int.appendZero(): String { - return if (this < 10) { - "0$this" - } else { - this.toString() - } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/String.kt b/app/src/main/java/com/casic/electric/detector/extensions/String.kt index a0db0eb..838d3ad 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/String.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/String.kt @@ -3,14 +3,11 @@ import android.content.Context import android.widget.TextView import com.casic.electric.detector.callback.OnImageCompressListener -import com.casic.electric.detector.model.ErrorMessageModel import com.casic.electric.detector.utils.FileType import com.casic.electric.detector.utils.LocaleConstant -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken +import com.google.gson.JsonParser import com.pengxh.kt.lite.extensions.createCompressImageDir import com.pengxh.kt.lite.utils.SaveKeyValues -import org.json.JSONObject import top.zibin.luban.Luban import top.zibin.luban.OnCompressListener import java.io.File @@ -18,18 +15,22 @@ /** * String扩展方法 */ -fun String.separateResponseState(): Boolean { +fun String.getResponseState(): Boolean { if (this.isBlank()) { return false } - return JSONObject(this).getBoolean("success") + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("success").asBoolean } -fun String.toErrorMessage(): String { - val errorModel = Gson().fromJson( - this, object : TypeToken() {}.type - ) - return errorModel.message.toString() +fun String.getResponseMessage(): String { + if (this.isBlank()) { + return "" + } + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("message").asString } /** @@ -131,4 +132,9 @@ } else { "6" } +} + +fun String.isNumber(): Boolean { + val regex = Regex("[-+]?\\d+(\\.\\d+)?") + return this.matches(regex) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt new file mode 100644 index 0000000..8b78a3c --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt @@ -0,0 +1,31 @@ +package com.casic.electric.detector.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import androidx.fragment.app.Fragment +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} + +fun ViewGroup.initImmersionBar(fragment: Fragment, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(fragment) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(fragment.requireContext())) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = fragment.requireContext().getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt new file mode 100644 index 0000000..84c9cd9 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt @@ -0,0 +1,3 @@ +package com.casic.electric.detector.model + +data class CalculateResult(val angle: Int, val direction: String, val distance: Int) diff --git a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java b/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java deleted file mode 100644 index 1574393..0000000 --- a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.casic.electric.detector.model; - -public class ErrorMessageModel { - private int code; - private String data; - private String exceptionClazz; - private String message; - private boolean isSuccess; - - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public String getExceptionClazz() { - return exceptionClazz; - } - - public void setExceptionClazz(String exceptionClazz) { - this.exceptionClazz = exceptionClazz; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public boolean isSuccess() { - return isSuccess; - } - - public void setSuccess(boolean success) { - isSuccess = success; - } -} diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt index 950fb91..f590226 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt @@ -90,10 +90,25 @@ /** * 上传工单中标识器信息 + * info中的主键 */ @GET("/ems/rs/task/update-task-mark") suspend fun uploadMarker( - @Query("userName") userId: String, - @Query("taskDetailId") taskId: String, + @Query("taskDetailId") taskId: String ): String + + /** + * 新建自由巡检任务 + * */ + @GET("ems/rs/task/addAppTask") + suspend fun createFreeTask( + @Query("patrollerId") patrollerId: String, + @Query("description") description: String + ): String + + /** + * 上传自由巡检过程中发现的标识器 + * */ + @POST("ems/event/uploadAppMarker.do") + suspend fun uploadTaskMarker(@Body requestBody: RequestBody): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt index 6834fc5..7836b28 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt @@ -1,5 +1,6 @@ package com.casic.electric.detector.retrofit +import com.casic.electric.detector.extensions.reformat import com.casic.electric.detector.utils.LabelDataClass import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.SmallLabelDataClass @@ -15,43 +16,32 @@ object RetrofitServiceManager { + private fun createApi(): RetrofitService { + val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String + val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String + val httpConfig = "http://${serverIp}:${serverPort}" + return RetrofitFactory.createRetrofit(httpConfig) + } + /** * 登录 */ suspend fun login(account: String, password: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.login(account, password) + return createApi().login(account, password) } /** * 更新版本 * */ suspend fun getApplicationVersion(): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getApplicationVersion() + return createApi().getApplicationVersion() } /** * 获取标识器信息文件 */ suspend fun getMarkerFile(userId: String, companyId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getMarkerFile(userId, companyId) + return createApi().getMarkerFile(userId, companyId) } /** @@ -64,39 +54,21 @@ "application/json;charset=UTF-8".toMediaType() ) - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getLabelPicture(requestBody) + return createApi().getLabelPicture(requestBody) } /** * 获取巡检工单 */ suspend fun getTask(userName: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getTask(userName) + return createApi().getTask(userName) } /** * 提交工单 */ suspend fun uploadTask(userId: String, taskId: String?, state: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadTask(userId, taskId.toString(), state) + return createApi().uploadTask(userId, taskId.toString(), state) } /** @@ -164,27 +136,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installLabel(res, multiParts[0], multiParts[1], null) + createApi().installLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installLabel(res, multiParts[0], null, null) + createApi().installLabel(res, multiParts[0], null, null) } else -> { - api.installLabel(res, null, null, null) + createApi().installLabel(res, null, null, null) } } } @@ -230,27 +196,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], null) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installSmallLabel(res, multiParts[0], null, null) + createApi().installSmallLabel(res, multiParts[0], null, null) } else -> { - api.installSmallLabel(res, null, null, null) + createApi().installSmallLabel(res, null, null, null) } } } @@ -279,27 +239,23 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2]) + createApi().uploadEvent( + taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2] + ) } 2 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) } 1 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) } else -> { - api.uploadEvent(taskIdMap, eventMap, null, null, null) + createApi().uploadEvent(taskIdMap, eventMap, null, null, null) } } } @@ -307,13 +263,27 @@ /** * 上传工单中标识器信息 */ - suspend fun uploadMarker(userName: String, taskDetailId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadMarker(userName, taskDetailId) + suspend fun uploadMarker(taskDetailId: String): String { + return createApi().uploadMarker(taskDetailId) + } + + /** + * 上传工单中标识器信息 + */ + suspend fun createFreeTask(patrollerId: String, description: String): String { + return createApi().createFreeTask(patrollerId, description) + } + + /** + * 上传自由巡检过程中发现的标识器 + */ + suspend fun uploadTaskMarker(taskId: String, models: ArrayList): String { + val param = JsonObject() + param.addProperty("taskId", taskId) + param.addProperty("ids", models.reformat()) + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return createApi().uploadTaskMarker(requestBody) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java index 4aba809..45d5a2f 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java +++ b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java @@ -1,8 +1,10 @@ package com.casic.electric.detector.utils; -public class GpioManager { +import android.util.Log; +public class GpioManager { + private static final String TAG = "GpioManager"; private static final int MT6761 = 0; private int selected; private final MT6761Gpio mt6761; @@ -38,6 +40,7 @@ * 璁剧疆GPIO杈撳嚭楂� * *********************************************************************/ public void setGpioHigh(String gpio) { + Log.d(TAG, "setGpioHigh: 调高电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioHigh(); @@ -48,6 +51,7 @@ * 璁剧疆GPIO杈撳嚭浣� * *********************************************************************/ public void setGpioLow(String gpio) { + Log.d(TAG, "setGpioLow: 调低电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioLow(); diff --git a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt deleted file mode 100644 index c589c4b..0000000 --- a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.electric.detector.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt index 4de12f2..9356f9a 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt @@ -13,7 +13,7 @@ ) const val PERMISSIONS_CODE = 999 - const val RADIUS_SIZE = 100f //相距多少米才聚合,单位:米 + const val RADIUS_SIZE = 100 //相距多少米才聚合,单位:米 const val AUTO_SAVE = "AUTO_SAVE" const val USER_ACCOUNT = "USER_ACCOUNT" @@ -28,10 +28,21 @@ const val APP_AUTHORITY = "com.casic.electric.detector.fileprovider" val POPUP_TITLES = arrayOf("更新数据", "下载工单", "关于软件", "事件上报", "标识器补全") - var CONDITION_ARRAY = arrayOf("种类", "编号", "名称", "所属区域", "所属道路", "运检单位", "责任人", "建设时间", "标识器ID") + var CONDITION_ARRAY = arrayOf( + "种类", + "编号", + "名称", + "所属区域", + "所属道路", + "运检单位", + "责任人", + "建设时间", + "标识器ID" + ) var CONTENT_ARRAY = arrayOf("电缆井", "电缆通道", "配电房", "开关站", "台区", "杆塔") var OBJECT_MODE_ARRAY = arrayOf("直线井", "转弯井", "丁字井", "十字井", "其他") - var WELL_COVER_MATERIAL_ARRAY_1 = arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") + var WELL_COVER_MATERIAL_ARRAY_1 = + arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") var WELL_COVER_MATERIAL_ARRAY_2 = arrayOf("水泥杆", "钢管杆", "铁塔", "其他") var CABINET_TYPE_ARRAY = arrayOf("无", "SM6", "SAFE", "RM6", "XGN15", "固体柜") var PIPE_MATERIAL_ARRAY = arrayOf("无", "PVC管", "波纹管", "镀锌钢管") @@ -42,7 +53,16 @@ var CROSS_PIPE_STATE_ARRAY = booleanArrayOf(false, false, false, false, false, false, false) var POINT_TYPE_ARRAY = arrayOf("管线", "管线附属物", "管线特征管点", "交叉穿越点") - var SPINNER_ARRAY = arrayOf("标识器ID", "所属区域", "所属线路", "所属道路", "权属单位", "安装部门", "安装时间", "备注") + var SPINNER_ARRAY = arrayOf( + "标识器ID", + "所属区域", + "所属线路", + "所属道路", + "权属单位", + "安装部门", + "安装时间", + "备注" + ) var DOWN_PIPE_TYPE_ARRAY = arrayOf("热力", "燃气", "供水", "电力", "通信") var BURY_METHOD_ARRAY = arrayOf("直埋", "圆管", "管块", "管沟", "架空") var COLOR_ARRAY = arrayOf("蓝色", "橙色", "红色", "黑色", "紫色", "黄色", "绿色") diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt index 4f0f2c7..61e55f6 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt @@ -14,14 +14,16 @@ import com.casic.electric.detector.callback.IAddressListener import com.casic.electric.detector.callback.ILocationListener -object LocationHub { - private const val kTag = "LocationHub" +class LocationHub constructor(context: Context) { - fun getCurrentLocation(context: Context, listener: ILocationListener) { - val locationClient = AMapLocationClient(context) + private val kTag = "LocationHub" + private val locationClient by lazy { AMapLocationClient(context) } + private val codeSearch by lazy { GeocodeSearch(context) } + + fun getCurrentLocation(isOnceLocation: Boolean, listener: ILocationListener) { val locationOption = AMapLocationClientOption() locationOption.locationMode = AMapLocationClientOption.AMapLocationMode.Hight_Accuracy - locationOption.isOnceLocation = true + locationOption.isOnceLocation = isOnceLocation locationClient.setLocationOption(locationOption) locationClient.setLocationListener { if (it.errorCode == 0) { @@ -36,9 +38,8 @@ locationClient.startLocation() } - fun antiCodingLocation(context: Context, location: Location, listener: IAddressListener) { + fun antiCodingLocation(location: Location, listener: IAddressListener) { try { - val codeSearch = GeocodeSearch(context) // 第一个参数表示一个LatLonPoint,第二参数表示范围多少米,第三个参数表示是火系坐标系还是GPS原生坐标系 val query = RegeocodeQuery( LatLonPoint(location.latitude, location.longitude), 10f, GeocodeSearch.AMAP @@ -55,4 +56,8 @@ e.printStackTrace() } } + + fun stopLocation() { + locationClient.stopLocation() + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt b/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt index aa1bdeb..e3d3289 100644 --- a/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt @@ -1,7 +1,6 @@ package com.casic.electric.detector.view import android.content.Context -import android.graphics.Color import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -12,10 +11,10 @@ import com.bumptech.glide.Glide import com.casic.electric.detector.R import com.casic.electric.detector.databinding.ActivityBigImageBinding +import com.casic.electric.detector.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class BigImageActivity : KotlinBaseActivity() { @@ -24,20 +23,12 @@ } override fun setupTopBarLayout() { - ImmerseStatusBarUtil.setColor(this, Color.BLACK) + binding.rootView.initImmersionBar(this, false, R.color.black) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - val index: Int = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return @@ -62,6 +53,14 @@ }) } + override fun observeRequestState() { + + } + + override fun initEvent() { + + } + inner class BigImageAdapter( private val context: Context, private val data: ArrayList ) : PagerAdapter() { diff --git a/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt b/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt index d3a89ca..6510104 100644 --- a/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt @@ -29,15 +29,15 @@ import com.casic.electric.detector.extensions.* import com.casic.electric.detector.utils.* import com.casic.electric.detector.vm.TaskViewModel -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia import com.luck.picture.lib.interfaces.OnResultCallbackListener import com.pengxh.kt.lite.extensions.* +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -53,7 +53,8 @@ private val context: Context = this@InstallLabelActivity private val gpioManager by lazy { GpioManager() } private val calendar by lazy { Calendar.getInstance() } - private val realPaths: ArrayList = ArrayList() //真实图片路径 + private val locationHub by lazy { LocationHub(this) } + private val realPaths = ArrayList() //真实图片路径 private var soundResId = 0 private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var soundPool: SoundPool @@ -67,12 +68,6 @@ override fun setupTopBarLayout() { binding.titleInclude.titleView.text = "安装新标识器" binding.titleInclude.titleView.setTextColor(R.color.themeColor.convertColor(this)) - - ImmersionBar.with(this) - .statusBarDarkFont(true) - .statusBarColor(R.color.mainBackground) - .init() - initLayoutImmersionBar(binding.rootView) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -126,7 +121,7 @@ binding.markerAttrInclude.remarkView3.setText("remarkView3".getDefaultValue()) //初始化图片九宫格 - imageAdapter = EditableImageAdapter(this, 3, 3f) + imageAdapter = EditableImageAdapter(this, 3, 3) binding.cameraInclude.addImageRecyclerView.adapter = imageAdapter taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] @@ -332,7 +327,7 @@ binding.markerAttrInclude.installTimeView.text = System.currentTimeMillis().timestampToCompleteDate() - LocationHub.getCurrentLocation(this, object : ILocationListener { + locationHub.getCurrentLocation(true, object : ILocationListener { override fun onAMapLocationGet(location: AMapLocation?) { if (location != null) { binding.markerAttrInclude.lngView.text = location.longitude.toString() @@ -518,8 +513,8 @@ weakReferenceHandler.postDelayed({ try { // 发送读标识器或搜索信号 - outputStream?.write("2".toByteArray()) - outputStream?.flush() + out.write("2".toByteArray()) + out.flush() } catch (e: IOException) { e.printStackTrace() } @@ -527,7 +522,7 @@ } } - override fun onDataReceived(buffer: ByteArray?, size: Int) { + override fun onDataReceived(buffer: ByteArray) { Log.d(kTag, "onDataReceived => " + buffer.contentToString()) if (buffer != null) { val message = weakReferenceHandler.obtainMessage() diff --git a/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt b/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt index 5bc2ac8..286bf4a 100644 --- a/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt @@ -24,7 +24,6 @@ import com.casic.electric.detector.extensions.* import com.casic.electric.detector.utils.* import com.casic.electric.detector.vm.TaskViewModel -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -33,9 +32,10 @@ import com.pengxh.kt.lite.extensions.isNetworkConnected import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -65,12 +65,6 @@ override fun setupTopBarLayout() { binding.titleInclude.titleView.text = "安装新电子标签" binding.titleInclude.titleView.setTextColor(R.color.themeColor.convertColor(this)) - - ImmersionBar.with(this) - .statusBarDarkFont(true) - .statusBarColor(R.color.mainBackground) - .init() - initLayoutImmersionBar(binding.rootView) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -103,7 +97,7 @@ binding.objectAttrInclude.objectRemarkView3.setText("objectRemarkView3".getDefaultValue()) //初始化图片九宫格 - imageAdapter = EditableImageAdapter(this, 3, 3f) + imageAdapter = EditableImageAdapter(this, 3, 3) binding.cameraInclude.addImageRecyclerView.adapter = imageAdapter taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] @@ -308,8 +302,8 @@ weakReferenceHandler.postDelayed({ try { // 发送读标识器或搜索信号 - outputStream?.write("2".toByteArray()) - outputStream?.flush() + out.write("2".toByteArray()) + out.flush() } catch (e: IOException) { e.printStackTrace() } @@ -317,7 +311,7 @@ } } - override fun onDataReceived(buffer: ByteArray?, size: Int) { + override fun onDataReceived(buffer: ByteArray) { if (buffer != null) { val message = weakReferenceHandler.obtainMessage() message.what = 2023081702 diff --git a/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt b/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt index 44d56ef..9c98b5f 100644 --- a/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt @@ -1,36 +1,29 @@ package com.casic.electric.detector.view import android.os.Bundle -import android.util.Log import androidx.lifecycle.ViewModelProvider import com.amap.api.navi.NaviSetting import com.casic.electric.detector.databinding.ActivityLoginBinding -import com.casic.electric.detector.extensions.initLayoutImmersionBar -import com.casic.electric.detector.utils.GpioManager -import com.casic.electric.detector.utils.LoadingDialogHub import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.vm.UserViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.getScreenHeight -import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog class LoginActivity : KotlinBaseActivity() { private val kTag = "LoginActivity" private lateinit var userViewModel: UserViewModel - private val gpioManager by lazy { GpioManager() } override fun initViewBinding(): ActivityLoginBinding { return ActivityLoginBinding.inflate(layoutInflater) } override fun initOnCreate(savedInstanceState: Bundle?) { - gpioManager.setGpioLow("18") //先把导航隐私政策声明,后面导航会用到 NaviSetting.updatePrivacyShow(this, true, true) NaviSetting.updatePrivacyAgree(this, true) @@ -60,11 +53,8 @@ val serversIp = binding.serversIpView.text.toString() val serversPort = binding.serversPortView.text.toString() if (account.isBlank() || password.isBlank() || serversIp.isBlank() || serversPort.isBlank()) { - AlertMessageDialog.Builder() - .setContext(this) - .setTitle("账号登录") - .setMessage("信息不能为空哦!") - .setPositiveButton("知道了") + AlertMessageDialog.Builder().setContext(this).setTitle("账号登录") + .setMessage("信息不能为空哦!").setPositiveButton("知道了") .setOnDialogButtonClickListener(object : AlertMessageDialog.OnDialogButtonClickListener { override fun onConfirmClick() { @@ -102,9 +92,6 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(true).init() - initLayoutImmersionBar(binding.rootView) - - Log.d(kTag, "setupTopBarLayout => [${getScreenWidth()}, ${getScreenHeight()}]") } override fun onResume() { diff --git a/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt b/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt index 36a8d55..a0a4aac 100644 --- a/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt @@ -1,15 +1,21 @@ package com.casic.electric.detector.view +import android.annotation.SuppressLint import android.app.AlertDialog +import android.app.Dialog import android.content.Context -import android.content.Intent import android.graphics.Color import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable +import android.media.AudioAttributes +import android.media.SoundPool import android.os.Bundle -import android.os.PowerManager -import android.provider.Settings +import android.os.CountDownTimer +import android.util.Log import android.view.KeyEvent +import android.view.View +import android.view.animation.Animation +import android.view.animation.RotateAnimation import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import com.amap.api.location.AMapLocation @@ -21,6 +27,8 @@ import com.amap.api.maps.model.LatLngBounds import com.amap.api.maps.model.MyLocationStyle import com.casic.electric.detector.R +import com.casic.electric.detector.adapter.EditableImageAdapter +import com.casic.electric.detector.base.SerialPortActivity import com.casic.electric.detector.bean.LabelBean import com.casic.electric.detector.bean.SmallLabelBean import com.casic.electric.detector.bean.TaskBean @@ -29,83 +37,109 @@ import com.casic.electric.detector.cluster.ClusterOverlay import com.casic.electric.detector.cluster.RegionItem import com.casic.electric.detector.databinding.ActivityMainBinding +import com.casic.electric.detector.databinding.DialogInstallMarkerBinding +import com.casic.electric.detector.databinding.DialogInstallSmallMarkerBinding +import com.casic.electric.detector.databinding.DialogSearchMarkerBinding import com.casic.electric.detector.extensions.appendExcelDownloadUrl import com.casic.electric.detector.extensions.drawCircle -import com.casic.electric.detector.extensions.initLayoutImmersionBar +import com.casic.electric.detector.extensions.hexToString +import com.casic.electric.detector.extensions.initImmersionBar +import com.casic.electric.detector.extensions.isNumber +import com.casic.electric.detector.extensions.toHex import com.casic.electric.detector.utils.DataBaseManager import com.casic.electric.detector.utils.ExcelHub -import com.casic.electric.detector.utils.LoadingDialogHub +import com.casic.electric.detector.utils.GpioManager import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.LocationHub import com.casic.electric.detector.utils.RouteOnMap import com.casic.electric.detector.vm.TaskViewModel import com.casic.electric.detector.widgets.QueryMarkerDialog import com.casic.electric.detector.widgets.SamplePopupWindow -import com.gyf.immersionbar.ImmersionBar -import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.callback.OnDownloadListener +import com.google.gson.Gson +import com.pengxh.kt.lite.extensions.binding import com.pengxh.kt.lite.extensions.createDownloadFileDir -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.dp2px +import com.pengxh.kt.lite.extensions.initDialogLayoutParams import com.pengxh.kt.lite.extensions.isNetworkConnected import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.toJson +import com.pengxh.kt.lite.utils.FileDownloadManager +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog +import com.pengxh.kt.lite.widget.dialog.AlertInputDialog +import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File +import java.text.DecimalFormat +import java.util.Calendar +import java.util.Timer +import java.util.TimerTask -class MainActivity : KotlinBaseActivity() { +@SuppressLint("all") +class MainActivity : SerialPortActivity() { private val kTag = "MainActivity" - private val context: Context = this@MainActivity + private val context = this@MainActivity + private val gpioManager by lazy { GpioManager() } private val samplePopupWindow by lazy { SamplePopupWindow(this) } + private val gson by lazy { Gson() } + private val locationHub by lazy { LocationHub(this) } + private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } + private val backDrawables by lazy { HashMap() } + private val installMarkerDialog by lazy { InstallMarkerDialog(this) } + private val installSmallMarkerDialog by lazy { InstallSmallMarkerDialog(this) } + private val searchDialog by lazy { SearchMarkerDialog(this) } private var clickTime: Long = 0 - private lateinit var wakeLock: PowerManager.WakeLock - private lateinit var aMap: AMap - private lateinit var taskViewModel: TaskViewModel - private lateinit var taskBean: TaskBean - private var latitude: Double = 0.0 - private var longitude: Double = 0.0 private var labels = ArrayList() private var smallLabels = ArrayList() private var clusterOverlay: ClusterOverlay? = null - private val backDrawables = HashMap() - private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } + private var latitude: Double = 0.0 + private var longitude: Double = 0.0 + private var isFreeTask = false + private var ids = ArrayList() + private var signalTask: TimerTask? = null + private var searchMarkerTimer: Timer? = null + private lateinit var aMap: AMap + private lateinit var taskBean: TaskBean + private lateinit var taskId: String + + /***inner class 需要用到*****start*/ + private val taskViewModel by lazy { ViewModelProvider(this)[TaskViewModel::class.java] } + 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 var soundResourceId = 0 + private var slowSoundResourceId = 0 + private var fastSoundResourceId = 0 + + /***inner class 需要用到*****end*/ override fun initViewBinding(): ActivityMainBinding { return ActivityMainBinding.inflate(layoutInflater) } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).statusBarColor(R.color.themeColor).init() - initLayoutImmersionBar(binding.rootView) - } - - override fun observeRequestState() { - + binding.rootView.initImmersionBar(this, false, R.color.themeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { - val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager - wakeLock = powerManager.run { - newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this@MainActivity.localClassName).apply { - acquire(60 * 60 * 1000L) - } - } + soundResourceId = soundPool.load(this, R.raw.ring3, 1) + slowSoundResourceId = soundPool.load(this, R.raw.ring4, 1) + fastSoundResourceId = soundPool.load(this, R.raw.ring2, 1) + //地图初始化 initMapConfig(savedInstanceState) samplePopupWindow.setPopupMenuItem(LocaleConstant.POPUP_TITLES) samplePopupWindow.setBackgroundDrawable(null) - taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] + //task网络请求监听 taskViewModel.markerFileResult.observe(this) { if (it.success == "true") { //清空之前的数据 @@ -122,11 +156,13 @@ val smallLabelDownloadUrl = urlArray[1].appendExcelDownloadUrl() //下载标识器 - labelDownloadUrl.downloadFile( - createDownloadFileDir().toString(), object : OnDownloadListener { - override fun onDownloadEnd(file: File?) { + FileDownloadManager.Builder().setDownloadFileSource(labelDownloadUrl) + .setFileSuffix("xls").setFileSaveDirectory(createDownloadFileDir()) + .setOnFileDownloadListener(object : + FileDownloadManager.OnFileDownloadListener { + override fun onDownloadEnd(file: File) { lifecycleScope.launch { - labels = ExcelHub.readLabel(file?.absolutePath) + labels = ExcelHub.readLabel(file.absolutePath) withContext(Dispatchers.IO) { labels.forEach { label -> DataBaseManager.get.insertLabel(label) @@ -137,21 +173,23 @@ } } - override fun onDownloadStart(totalBytes: Long) { + override fun onFailure(throwable: Throwable) { } - override fun onProgressChanged(currentBytes: Long) { + override fun onProgressChanged(progress: Int) { } - }) + }).build().start() //下载附属标识器 - smallLabelDownloadUrl.downloadFile( - createDownloadFileDir().toString(), object : OnDownloadListener { - override fun onDownloadEnd(file: File?) { + FileDownloadManager.Builder().setDownloadFileSource(smallLabelDownloadUrl) + .setFileSuffix("xls").setFileSaveDirectory(createDownloadFileDir()) + .setOnFileDownloadListener(object : + FileDownloadManager.OnFileDownloadListener { + override fun onDownloadEnd(file: File) { lifecycleScope.launch { - smallLabels = ExcelHub.readSmallLabel(file?.absolutePath) + smallLabels = ExcelHub.readSmallLabel(file.absolutePath) withContext(Dispatchers.IO) { smallLabels.forEach { label -> DataBaseManager.get.insertSmallLabel(label) @@ -160,14 +198,14 @@ } } - override fun onDownloadStart(totalBytes: Long) { + override fun onFailure(throwable: Throwable) { } - override fun onProgressChanged(currentBytes: Long) { + override fun onProgressChanged(progress: Int) { } - }) + }).build().start() } } } @@ -175,11 +213,8 @@ // if (it.success == "true") { // //清空之前的数据 // DataBaseManager.get.clearTasks() -// AlertMessageDialog.Builder() -// .setContext(this) -// .setTitle("温馨提示") -// .setMessage("您有${it.message.size}个新任务!") -// .setPositiveButton("知道了") +// AlertMessageDialog.Builder().setContext(this).setTitle("温馨提示") +// .setMessage("您有${it.message.size}个新任务!").setPositiveButton("知道了") // .setOnDialogButtonClickListener(object : // AlertMessageDialog.OnDialogButtonClickListener { // override fun onConfirmClick() { @@ -188,19 +223,24 @@ // }).build().show() // } // } + taskViewModel.freeTaskResult.observe(this) { taskId = it } + taskViewModel.uploadTaskMarkerResult.observe(this) { + "自由巡检任务已完成".show(this) + ids.clear() + } } override fun initEvent() { binding.rightImageView.setOnClickListener { - CoroutineScope(Dispatchers.Main).launch { + lifecycleScope.launch(Dispatchers.Main) { val labels = withContext(Dispatchers.IO) { DataBaseManager.get.queryLabelById("0") } if (labels.isNotEmpty()) { samplePopupWindow.setShowPosition(4) } - val x = binding.rightImageView.width - samplePopupWindow.width - 1f.dp2px(context) - samplePopupWindow.showAsDropDown(binding.rightImageView, x, 1f.dp2px(context)) + val x = binding.rightImageView.width - samplePopupWindow.width - 1.dp2px(context) + samplePopupWindow.showAsDropDown(binding.rightImageView, x, 1.dp2px(context)) } } @@ -219,35 +259,33 @@ //安装。上传,然后存入本地库 binding.installButton.setOnClickListener { - AlertControlDialog.Builder() - .setContext(context) - .setTitle("提示") - .setMessage("请选择安装对象") - .setPositiveButton("标识器") - .setNegativeButton("电子标签") - .setOnDialogButtonClickListener(object : + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("请选择安装对象").setPositiveButton("标识器") + .setNegativeButton("电子标签").setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { //标识器 - navigatePageTo() + /** + * 改为Dialog方式,避免频繁打开/关闭串口 + * */ + installMarkerDialog.show() } override fun onCancelClick() { //电子标签 - navigatePageTo() + /** + * 改为Dialog方式,避免频繁打开/关闭串口 + * */ + installSmallMarkerDialog.show() } }).build().show() } //查看 binding.viewButton.setOnClickListener { - QueryMarkerDialog.Builder() - .setContext(this) - .setTitle("查看标识器") - .setConditionArray(LocaleConstant.CONDITION_ARRAY) - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : + QueryMarkerDialog.Builder().setContext(this).setTitle("查看标识器") + .setConditionArray(LocaleConstant.CONDITION_ARRAY).setNegativeButton("取消") + .setPositiveButton("确定").setOnDialogButtonClickListener(object : QueryMarkerDialog.OnDialogButtonClickListener { override fun onConfirmClick( selectedCondition: String, vararg contentValue: String @@ -310,30 +348,25 @@ // arrayList.add("任务${index + 1}:${taskBean.taskId},${taskBean.desc}") // } // -// BottomActionSheet.Builder() -// .setContext(this) -// .setItemTextColor(Color.BLUE) +// BottomActionSheet.Builder().setContext(this).setItemTextColor(Color.BLUE) // .setActionItemTitle(arrayList) // .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { // override fun onActionItemClick(position: Int) { // val taskBean = task[position] // SaveKeyValues.putValue(LocaleConstant.TASK_ID, taskBean.taskId) -// AlertControlDialog.Builder() -// .setContext(context) -// .setTitle("提示") -// .setMessage("请选择操作方式") -// .setPositiveButton("执行工单") +// AlertControlDialog.Builder().setContext(context).setTitle("提示") +// .setMessage("请选择操作方式").setPositiveButton("执行工单") // .setNegativeButton("提交工单") // .setOnDialogButtonClickListener(object : // AlertControlDialog.OnDialogButtonClickListener { // override fun onConfirmClick() { // detectRedrawGraphic(taskBean.taskId) +// +// val latLng = LatLng( +// taskBean.lat.toDouble(), taskBean.lng.toDouble() +// ) // aMap.moveCamera( -// CameraUpdateFactory.newLatLngZoom( -// LatLng( -// taskBean.lat.toDouble(), taskBean.lng.toDouble() -// ), 15f -// ) +// CameraUpdateFactory.newLatLngZoom(latLng, 16f) // ) // uploadTask(taskBean.taskId, "1") // } @@ -345,15 +378,12 @@ // } // }).build().show() // } else { -// AlertMessageDialog.Builder() -// .setContext(this) -// .setTitle("温馨提示") -// .setMessage("现有任务已完成,请点击右上角菜单按钮下载新工单!") -// .setPositiveButton("知道了") -// .setOnDialogButtonClickListener(object : +// AlertMessageDialog.Builder().setContext(this).setTitle("温馨提示") +// .setMessage("现有任务已完成,请点击右上角菜单下载新工单或者开始自由巡检") +// .setPositiveButton("知道了").setOnDialogButtonClickListener(object : // AlertMessageDialog.OnDialogButtonClickListener { // override fun onConfirmClick() { -// +// startFreeTask() // } // }).build().show() // } @@ -361,7 +391,118 @@ //探测 binding.detectionButton.setOnClickListener { -// navigatePageTo() + /** + * 改为Dialog方式,避免频繁打开/关闭串口 + * */ + searchDialog.show() + } + + //自由巡检 + binding.stopFreeTaskButton.setOnLongClickListener { + AlertMessageDialog.Builder().setContext(this).setTitle("温馨提示") + .setMessage("是否确定结束此次自由巡检任务?").setPositiveButton("是") + .setOnDialogButtonClickListener(object : + AlertMessageDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + isFreeTask = false + soundPool.autoPause() + + //降低串口电位 + gpioManager.setGpioLow("18") + + taskViewModel.uploadTaskMarker(taskId, ids) + binding.stopFreeTaskButton.visibility = View.GONE + } + }).build().show() + true + } + } + + private fun startFreeTask() { + AlertInputDialog.Builder().setContext(this).setTitle("新建自由巡检任务") + .setHintMessage("请输入自由巡检任务简要描述").setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : AlertInputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String + taskViewModel.createFreeTask(userId, value) + + //调高串口电位 + gpioManager.setGpioHigh("18") + + soundPool.play(soundResourceId, 1f, 1f, 0, -1, 1f) + isFreeTask = true + //自由巡检 + signalTask = object : TimerTask() { + override fun run() { + out.write('2'.code) + out.flush() + } + } + searchMarkerTimer = Timer() + searchMarkerTimer?.apply { + schedule(signalTask, 0, 100) + } + + binding.stopFreeTaskButton.visibility = View.VISIBLE + } + + override fun onCancelClick() {} + }).build().show() + } + + override fun onDataReceived(buffer: ByteArray) { + val hex = buffer.toHex() + Log.d(kTag, "$kTag => $hex") + if (searchDialog.isDetectMarker) { + searchDialog.bindingValue(hex) +// } else if (installMarkerDialog.isReadMarker) { +// val markerId = hex.take(20).hexToString() +// if (markerId.isNumber()) { +// installMarkerDialog.bindingValue(markerId) +// } +// } else if (installSmallMarkerDialog.isReadMarker) { +// val markerId = hex.take(20).hexToString() +// if (markerId.isNumber()) { +// installSmallMarkerDialog.bindingValue(markerId) +// } + } else if (isFreeTask) { + val markerId = hex.take(20).hexToString() + if (markerId.isNumber()) { + "标识器${markerId}已探测".show(this) + ids.add(markerId) + } + } + } + + override fun observeRequestState() { + taskViewModel.loadState.observe(this) { + when (it) { + LoadState.Loading -> { + if (installMarkerDialog.isInstallMarker || installSmallMarkerDialog.isInstallMarker) { + LoadingDialogHub.show(this, "标识器安装中,请稍后...") + } else if (searchDialog.isDetectMarker) { + searchDialog.taskBean?.apply { + "标识器${this.markerId}已探测!".show(context) +// DataBaseManager.get.updateTaskLabel(this) + } + } else { + LoadingDialogHub.show(this, "提交工单中,请稍后") + } + } + + else -> { + if (installMarkerDialog.isInstallMarker) { + installMarkerDialog.dismiss() + installMarkerDialog.isInstallMarker = false + } else if (installSmallMarkerDialog.isInstallMarker) { + installSmallMarkerDialog.dismiss() + installSmallMarkerDialog.isInstallMarker = false + } + LoadingDialogHub.dismiss() + } + } + detectRedrawGraphic(taskBean.taskId) } } @@ -375,6 +516,7 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜 //显示定位小蓝点 val locationStyle = MyLocationStyle() locationStyle.interval(2000) @@ -387,7 +529,7 @@ longitude = it.longitude latitude = it.latitude //经纬度逆编码 - LocationHub.antiCodingLocation(context, it) { address -> + locationHub.antiCodingLocation(it) { address -> binding.currentLocationView.text = address } } @@ -417,7 +559,7 @@ } private fun moveToCurrentLocation() { - LocationHub.getCurrentLocation(this, object : ILocationListener { + locationHub.getCurrentLocation(true, object : ILocationListener { override fun onAMapLocationGet(location: AMapLocation?) { if (location != null) { aMap.moveCamera( @@ -432,46 +574,35 @@ }) } - //更新数据 - private fun updateLabels() { - AlertControlDialog.Builder() - .setContext(this) - .setTitle("提示") - .setMessage("是否更新数据?") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onConfirmClick() { - if (isNetworkConnected()) { - val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") - val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") - - LoadingDialogHub.show(this@MainActivity, "获取标识器信息中,请稍后") - //TODO 设计如此,都传companyId - taskViewModel.getMarkerFile(companyId.toString(), companyId.toString()) - } else { - NoNetworkDialog.Builder() - .setContext(context) - .setOnDialogButtonClickListener(object : - NoNetworkDialog.OnDialogButtonClickListener { - override fun onButtonClick() { - val intent = Intent(Settings.ACTION_SETTINGS) - startActivity(intent) - } - }).build().show() - } - } - - override fun onCancelClick() { - - } - }).build().show() - } +// private fun saveTaskInformation(it: TaskModel) { +// val userName = SaveKeyValues.getValue(LocaleConstant.USER_NAME, "") as String +// if (it.message.size > 0) { +// it.message.forEach { messageModel -> +// val count = DataBaseManager.get.countTaskById(messageModel.id.toString()) +// if (count == 0) { +// messageModel.taskDetailInfos.forEach { info -> +// DataBaseManager.get.insertTaskInformation( +// userName, +// messageModel.description, +// info.taskId.toString(), +// info.id.toString(), +// info.markerId.toString(), +// info.markerIdReal.toString(), +// info.longitude.toString(), +// info.latitude.toString(), +// messageModel.status +// ) +// } +// } +// } +// "工单下载成功!".show(context) +// } +// } private fun showLabelsOnMap() { clusterOverlay?.onDestroy() val clusterItems = ArrayList() + labels.forEach { val latLng = LatLng(it.latitude.toDouble(), it.longitude.toDouble(), false) val regionItem = RegionItem(latLng, it.markerId.toString()) @@ -480,7 +611,7 @@ clusterOverlay = ClusterOverlay(context, aMap, clusterItems, regionRadius) clusterOverlay?.setClusterRender { clusterNum -> - val radius = 80f.dp2px(context) + val radius = 80.dp2px(context) if (clusterNum == 0) { var bitmapDrawable = backDrawables[0] if (bitmapDrawable == null) { @@ -546,9 +677,7 @@ val latLngBounds = builder.build() aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 0)) - BottomActionSheet.Builder() - .setContext(this) - .setItemTextColor(Color.BLUE) + BottomActionSheet.Builder().setContext(this).setItemTextColor(Color.BLUE) .setActionItemTitle(listOf("标识器信息", "附属电子标签信息", "到这里去")) .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { override fun onActionItemClick(position: Int) { @@ -578,12 +707,7 @@ showElectricMarkers(electricMarkers) } - 2 -> { - RouteOnMap.startNavigation( - context, item.tag, - LatLng(item.position.latitude, item.position.longitude) - ) - } + 2 -> RouteOnMap.startNavigation(context, item.tag, latLng) } } }).build().show() @@ -591,14 +715,74 @@ } private fun showElectricMarkers(markers: ArrayList) { - AlertDialog.Builder(context) - .setIcon(R.mipmap.ic_launcher) - .setTitle("电子标签列表") + AlertDialog.Builder(context).setIcon(R.mipmap.ic_launcher).setTitle("电子标签列表") .setSingleChoiceItems(markers.toTypedArray(), -1) { _, which -> navigatePageTo(markers[which]) }.show() } + private fun detectRedrawGraphic(taskId: String) { +// val tasks = DataBaseManager.get.queryTaskById(taskId) +// if (tasks.isNotEmpty()) { +// tasks.forEach { +// val latLng = LatLng(it.lat.toDouble(), it.lng.toDouble()) +// val otMarkerOptions = MarkerOptions() +// otMarkerOptions.position(latLng) +// otMarkerOptions.visible(true) // 设置可见 +// if (it.state == "未开始") { +// otMarkerOptions.icon( +// BitmapDescriptorFactory.fromBitmap( +// BitmapFactory.decodeResource(resources, R.mipmap.label_red1) +// ) +// ).period(99).title("工单标识器").snippet(it.markerId) +// } else { +// otMarkerOptions.icon( +// BitmapDescriptorFactory.fromBitmap( +// BitmapFactory.decodeResource(resources, R.mipmap.label_blue1) +// ) +// ).period(99).title("工单标识器").snippet(it.markerId) +// } +// aMap.addMarker(otMarkerOptions) +// } +// } + showLabelsOnMap() + } + + private fun uploadTask(taskId: String?, state: String) { + if (isNetworkConnected()) { + val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String + taskViewModel.uploadTask(userId, taskId, state) + } else { + "网络连接已断开,请检查".show(this) + } + } + + //更新数据 + private fun updateLabels() { + AlertControlDialog.Builder().setContext(this).setTitle("提示").setMessage("是否更新数据?") + .setNegativeButton("取消").setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + if (isNetworkConnected()) { + val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") + + LoadingDialogHub.show(this@MainActivity, "获取标识器信息中,请稍后") + /** + * 后台设计如此,都传companyId + * */ + taskViewModel.getMarkerFile(companyId.toString(), companyId.toString()) + } else { + "网络连接已断开,请检查".show(context) + } + } + + override fun onCancelClick() { + + } + }).build().show() + } + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { return if (keyCode == KeyEvent.KEYCODE_BACK) { if (System.currentTimeMillis() - clickTime > 2000) { @@ -643,8 +827,270 @@ } override fun onDestroy() { - wakeLock.release() super.onDestroy() binding.mapView.onDestroy() + signalTask?.cancel() + searchMarkerTimer?.cancel() + soundPool.release() + locationHub.stopLocation() + //降低串口电位 + gpioManager.setGpioLow("18") + } + + /**安装标识器对话框******************************************************************************/ + inner class InstallMarkerDialog(context: Context) : Dialog(context) { + + private val binding: DialogInstallMarkerBinding by binding() + private val calendar by lazy { Calendar.getInstance() } + private val realPaths = ArrayList() //真实图片路径 + private lateinit var imageAdapter: EditableImageAdapter + + var isReadMarker = false + var isInstallMarker = false + } + + /**安装小标签对话框******************************************************************************/ + inner class InstallSmallMarkerDialog(context: Context) : Dialog(context) { + + private val binding: DialogInstallSmallMarkerBinding by binding() + private val calendar by lazy { Calendar.getInstance() } + private val realPaths = ArrayList() //真实图片路径 + private lateinit var imageAdapter: EditableImageAdapter + + var isReadMarker = false + var isInstallMarker = false + } + + /**探测标识器对话框******************************************************************************/ + inner class SearchMarkerDialog(context: Context) : Dialog(context) { + + private val binding: DialogSearchMarkerBinding by binding() + private val decimal by lazy { DecimalFormat("0.0") } + private val degreeCache by lazy { HashMap() } + private var isPlaying = false + private var markerId = "" + private lateinit var searchMarkerTimer: Timer + private lateinit var signalTask: TimerTask + private lateinit var energyTask: TimerTask + private lateinit var countDownTimer: CountDownTimer + + var isDetectMarker = false + var taskBean: TaskBean? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.initDialogLayoutParams(1f) + binding.depthButton.setOnClickListener { + signalTask.cancel() + energyTask.cancel() + searchMarkerTimer.cancel() + + out.write('3'.code) +// val result = DataBaseManager.get.queryLabelById(markerId) +// if (result.isNotEmpty()) { +// val tag = when (result.first().identifierType) { +// "EM30" -> '7' +// "EM50" -> '8' +// "EM14" -> '9' +// else -> '1' +// } +// if (tag == '1') { +// "此标识器无法读取埋深!".show(context) +// } else { +// // 发送读取标识器埋设深度指令 +// LoadingDialogHub.show(this@MainActivity, "正在测距,请稍后...") +// out.write(tag.code) +// out.flush() +// countDownTimer = object : CountDownTimer(15 * 1000, 1000) { +// override fun onTick(millisUntilFinished: Long) { +// +// } +// +// override fun onFinish() { +// LoadingDialogHub.dismiss() +// "探测此标识器深度超时,请重试".show(context) +// initTimer() +// } +// } +// countDownTimer.start() +// } +// } else { +// "标识器未安装,安装成功后才可读取埋深!".show(context) +// } + } + + binding.markerInfoButton.setOnClickListener { + //查库 + val result = DataBaseManager.get.queryLabelById(markerId) + if (result.isNotEmpty()) { +// context.navigatePageTo(result.first().toJson()) + } else { +// context.navigatePageTo(markerId) + } + } + } + + override fun onStart() { + super.onStart() + //调高串口电位 + gpioManager.setGpioHigh("18") + + initTimer() + + isDetectMarker = true + + //角度 + degreeCache["lastDegree"] = 0f + } + + fun bindingValue(hex: String) { + if (hex.startsWith("4E")) { + try { + //4E转为String为N,代表能量值 + //用能量值转动表盘 + val energyResponse = hex.take(10).hexToString() + val energy = energyResponse.substring(1).toInt() + if (energy >= 4000) { + isPlaying = if (!isPlaying) { + soundPool.play(fastSoundResourceId, 1f, 1f, 0, 0, 1f) + true + } else { + soundPool.pause(fastSoundResourceId) + false + } + } else { + isPlaying = if (!isPlaying) { + soundPool.play(slowSoundResourceId, 1f, 1f, 0, 0, 1f) + true + } else { + soundPool.pause(slowSoundResourceId) + false + } + } + + binding.resultTextView.text = "信号能量值:${energyResponse}" + + //转换为转动的角度 + val degree = (energy.toFloat() / (50 * 100)) * 180 + binding.energyValueView.text = decimal.format(degree) + + degreeCache["lastDegree"]?.apply { + val animation = RotateAnimation( + this, degree, + Animation.RELATIVE_TO_SELF, 0.5f, + Animation.RELATIVE_TO_SELF, 0.5f + ) + animation.duration = 0 + animation.fillAfter = true + binding.needleView.startAnimation(animation) + } + + //保存旋转后的角度 + degreeCache["lastDegree"] = degree + + if (energy <= 700) {//18° + binding.energyTipsView.text = "标识器信号较弱,可能距离较远" + binding.energyTipsView.setTextColor(Color.parseColor("#8D1717")) + binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_red) + + binding.depthButton.isEnabled = false + binding.depthButton.setTextColor(Color.parseColor("#CCCCCC")) + binding.depthButton.setBackgroundResource(R.mipmap.left_button_disable) + binding.markerInfoButton.isEnabled = false + binding.markerInfoButton.setTextColor(Color.parseColor("#CCCCCC")) + binding.markerInfoButton.setBackgroundResource(R.mipmap.right_button_disable) + + binding.searchResultView.text = "未检测到标识器" + binding.searchResultView.setTextColor(Color.parseColor("#8D1717")) + binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_red) + } else if (energy >= 4100) {//148° + binding.energyTipsView.text = "标识器信号极强,可能在正下方" + binding.energyTipsView.setTextColor(Color.parseColor("#428d00")) + binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_green) + } else {//[18°,148°] + binding.energyTipsView.text = "已靠近标识器,请继续移动位置" + binding.energyTipsView.setTextColor(Color.parseColor("#8C5700")) + binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_yellow) + } + } catch (e: NumberFormatException) { + e.printStackTrace() + } + } else if (hex.startsWith("53")) { + LoadingDialogHub.dismiss() + countDownTimer.cancel() + try { + val depthResponse = hex.take(10).hexToString() + val depth = depthResponse.drop(2).toInt() + AlertMessageDialog.Builder().setContext(context).setTitle("温馨提示") + .setMessage("标识器埋深:${depth}厘米").setPositiveButton("知道了") + .setOnDialogButtonClickListener(object : + AlertMessageDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + initTimer() + } + }).build().show() + } catch (e: NumberFormatException) { + e.printStackTrace() + } + } else { + val id = hex.take(20).hexToString() + if (id.isNumber()) { + markerId = id + + binding.depthButton.isEnabled = true + binding.depthButton.setTextColor(Color.WHITE) + binding.depthButton.setBackgroundResource(R.mipmap.left_button_enable) + binding.markerInfoButton.isEnabled = true + binding.markerInfoButton.setTextColor(Color.WHITE) + binding.markerInfoButton.setBackgroundResource(R.mipmap.right_button_enable) + + binding.searchResultView.text = "已检测到标识器" + binding.searchResultView.setTextColor(Color.parseColor("#428d00")) + binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_green) + + //自动上传标识器 +// taskBean = DataBaseManager.get.queryTaskLabelByIdAndState(markerId, "未开始") +// taskBean?.apply { +// /** +// * 此taskCode是 [com.casic.detector.model.TaskModel.MessageModel.TaskDetailInfosModel] 里面的主键,也就是这个标签在数据库里面的主键 +// * */ +// taskViewModel.uploadMarker(taskCode) +// } + } + } + } + + private fun initTimer() { + searchMarkerTimer = Timer() + + signalTask = object : TimerTask() { + override fun run() { + out.write('2'.code) + out.flush() + } + } + + energyTask = object : TimerTask() { + override fun run() { + out.write('6'.code) + out.flush() + } + } + + //错开信号和能量定时器 + searchMarkerTimer.schedule(signalTask, 0, 201) + searchMarkerTimer.schedule(energyTask, 0, 251) + } + + override fun dismiss() { + signalTask.cancel() + energyTask.cancel() + searchMarkerTimer.cancel() + //降低串口电位 + gpioManager.setGpioLow("18") + isDetectMarker = false + soundPool.autoPause() + super.dismiss() + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt b/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt index 6a00429..cbd6137 100644 --- a/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt @@ -13,18 +13,16 @@ import com.casic.electric.detector.R import com.casic.electric.detector.databinding.ActivityVersionControlBinding import com.casic.electric.detector.extensions.appendDownloadUrl -import com.casic.electric.detector.extensions.initLayoutImmersionBar +import com.casic.electric.detector.extensions.initImmersionBar import com.casic.electric.detector.utils.FileType -import com.casic.electric.detector.utils.LoadingDialogHub import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.vm.VersionViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.createDownloadFileDir -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.FileDownloadManager +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import java.io.File @@ -90,8 +88,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(true).init() - initLayoutImmersionBar(binding.rootView) + binding.rootView.initImmersionBar(this, true, R.color.white) binding.titleInclude.titleView.visibility = View.GONE } @@ -108,22 +105,26 @@ val downloadPath = url!!.appendDownloadUrl(FileType.APK) Log.d(kTag, "downloadApk => $downloadPath") //开始下载 - downloadPath.downloadFile(createDownloadFileDir().toString(), object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() - } + FileDownloadManager.Builder() + .setDownloadFileSource(downloadPath) + .setFileSuffix("apk") + .setFileSaveDirectory(createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadEnd(file: File) { + progressDialog.dismiss() + progressDialog.progress = 0 + //安装APK + installApk(file) + } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } + override fun onFailure(throwable: Throwable) { - override fun onDownloadEnd(file: File?) { - progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK - installApk(file) - } - }) + } + + override fun onProgressChanged(progress: Int) { + progressDialog.progress = progress + } + }).build().start() } private fun installApk(apkPackage: File?) { diff --git a/app/src/main/java/com/casic/electric/detector/vm/TaskViewModel.kt b/app/src/main/java/com/casic/electric/detector/vm/TaskViewModel.kt index 476a5f0..4b0bed6 100644 --- a/app/src/main/java/com/casic/electric/detector/vm/TaskViewModel.kt +++ b/app/src/main/java/com/casic/electric/detector/vm/TaskViewModel.kt @@ -2,125 +2,156 @@ import androidx.lifecycle.MutableLiveData import com.casic.electric.detector.base.BaseApplication -import com.casic.electric.detector.extensions.convertChinese -import com.casic.electric.detector.extensions.separateResponseState -import com.casic.electric.detector.extensions.toErrorMessage +import com.casic.electric.detector.extensions.getResponseMessage +import com.casic.electric.detector.extensions.getResponseState import com.casic.electric.detector.model.MarkerFileModel import com.casic.electric.detector.retrofit.RetrofitServiceManager import com.casic.electric.detector.utils.LabelDataClass +import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.SmallLabelDataClass import com.google.gson.Gson +import com.google.gson.JsonParser import com.google.gson.reflect.TypeToken +import com.pengxh.kt.lite.base.BaseViewModel import com.pengxh.kt.lite.extensions.launch import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.SaveKeyValues class TaskViewModel : BaseViewModel() { private val gson by lazy { Gson() } val markerFileResult = MutableLiveData() -// val taskResult = MutableLiveData() + + // val taskResult = MutableLiveData() + val freeTaskResult = MutableLiveData() + val uploadTaskMarkerResult = MutableLiveData() + + fun createFreeTask(patrollerId: String, description: String) = launch({ + val response = RetrofitServiceManager.createFreeTask(patrollerId, description) + if (response.getResponseState()) { + val element = JsonParser.parseString(response) + val jsonObject = element.asJsonObject + freeTaskResult.value = jsonObject.get("taskId").asInt.toString() + } else { + response.getResponseMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) + + fun uploadTaskMarker(taskId: String, models: ArrayList) = launch({ + val response = RetrofitServiceManager.uploadTaskMarker(taskId, models) + if (response.getResponseState()) { + val element = JsonParser.parseString(response) + val jsonObject = element.asJsonObject + uploadTaskMarkerResult.value = jsonObject.get("success").asString + } else { + response.getResponseMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) fun getMarkerFile(userId: String, companyId: String) = launch({ val response = RetrofitServiceManager.getMarkerFile(userId, companyId) - if (response.separateResponseState()) { + if (response.getResponseState()) { markerFileResult.value = gson.fromJson( response, object : TypeToken() {}.type ) } else { - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { - it.convertChinese().show(BaseApplication.get()) + it.printStackTrace() }) -// fun getTask(userName: String) = launch({ -// val response = RetrofitServiceManager.getTask(userName) -// if (response.separateResponseState()) { + fun getTask(userName: String) = launch({ + val response = RetrofitServiceManager.getTask(userName) + if (response.getResponseState()) { // taskResult.value = gson.fromJson( // response, object : TypeToken() {}.type // ) -// } else { -// response.toErrorMessage().show(BaseApplication.get()) -// } -// }, { -// it.convertChinese().show(BaseApplication.get()) -// }) + } else { + response.getResponseMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) fun installLabel(labelData: LabelDataClass) = launch({ loadState.value = LoadState.Loading val response = RetrofitServiceManager.installLabel(labelData) - if (response.separateResponseState()) { + if (response.getResponseState()) { loadState.value = LoadState.Success } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { + it.printStackTrace() loadState.value = LoadState.Fail - it.convertChinese().show(BaseApplication.get()) }) fun installSmallLabel(labelData: SmallLabelDataClass) = launch({ loadState.value = LoadState.Loading val response = RetrofitServiceManager.installSmallLabel(labelData) - if (response.separateResponseState()) { + if (response.getResponseState()) { loadState.value = LoadState.Success } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { + it.printStackTrace() loadState.value = LoadState.Fail - it.convertChinese().show(BaseApplication.get()) }) -// fun uploadTask(userId: String, taskId: String?, state: String) = launch({ -// loadState.value = LoadState.Loading -// val response = RetrofitServiceManager.uploadTask(userId, taskId, state) -// if (response.separateResponseState()) { -// loadState.value = LoadState.Success -// if (state == "2") { -// "工单${taskId}已提交!".show(BaseApplication.get()) -// //删除本地数据库 + fun uploadTask(userId: String, taskId: String?, state: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.uploadTask(userId, taskId, state) + if (response.getResponseState()) { + loadState.value = LoadState.Success + if (state == "2") { + "工单${taskId}已提交!".show(BaseApplication.get()) + //删除本地数据库 // DataBaseManager.get.deleteTaskById(taskId) -// SaveKeyValues.putValue(LocaleConstant.TASK_ID, "") -// } -// } else { -// loadState.value = LoadState.Fail -// response.toErrorMessage().show(BaseApplication.get()) -// } -// }, { -// loadState.value = LoadState.Fail -// it.convertChinese().show(BaseApplication.get()) -// }) + SaveKeyValues.putValue(LocaleConstant.TASK_ID, "") + } + } else { + loadState.value = LoadState.Fail + response.getResponseMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + loadState.value = LoadState.Fail + }) fun uploadEvent(taskId: String, event: String, realPaths: ArrayList) = launch({ loadState.value = LoadState.Loading val response = RetrofitServiceManager.uploadEvent(taskId, event, realPaths) - if (response.separateResponseState()) { + if (response.getResponseState()) { loadState.value = LoadState.Success } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { + it.printStackTrace() loadState.value = LoadState.Fail - it.convertChinese().show(BaseApplication.get()) }) - fun uploadMarker(userName: String, taskDetailId: String) = launch({ + fun uploadMarker(taskDetailId: String) = launch({ loadState.value = LoadState.Loading - val response = RetrofitServiceManager.uploadMarker(userName, taskDetailId) - if (response.separateResponseState()) { + val response = RetrofitServiceManager.uploadMarker(taskDetailId) + if (response.getResponseState()) { loadState.value = LoadState.Success } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { + it.printStackTrace() loadState.value = LoadState.Fail - it.convertChinese().show(BaseApplication.get()) }) } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt b/app/src/main/java/com/casic/electric/detector/extensions/Context.kt deleted file mode 100644 index fcf36a7..0000000 --- a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.casic.electric.detector.extensions - -import android.content.Context -import android.view.ViewGroup -import com.pengxh.kt.lite.extensions.getStatusBarHeight - -/** - * 设置沉浸式状态栏,兼容Android 11+ - * */ -fun Context.initLayoutImmersionBar(rootView: ViewGroup) { - rootView.setPadding(0, this.getStatusBarHeight(), 0, 0) - rootView.requestLayout() -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt index 6e08b27..e98408a 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt @@ -13,12 +13,4 @@ paint.color = color canvas.drawArc(rectF, 0f, 360f, true, paint) return bitmap -} - -fun Int.appendZero(): String { - return if (this < 10) { - "0$this" - } else { - this.toString() - } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/String.kt b/app/src/main/java/com/casic/electric/detector/extensions/String.kt index a0db0eb..838d3ad 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/String.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/String.kt @@ -3,14 +3,11 @@ import android.content.Context import android.widget.TextView import com.casic.electric.detector.callback.OnImageCompressListener -import com.casic.electric.detector.model.ErrorMessageModel import com.casic.electric.detector.utils.FileType import com.casic.electric.detector.utils.LocaleConstant -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken +import com.google.gson.JsonParser import com.pengxh.kt.lite.extensions.createCompressImageDir import com.pengxh.kt.lite.utils.SaveKeyValues -import org.json.JSONObject import top.zibin.luban.Luban import top.zibin.luban.OnCompressListener import java.io.File @@ -18,18 +15,22 @@ /** * String扩展方法 */ -fun String.separateResponseState(): Boolean { +fun String.getResponseState(): Boolean { if (this.isBlank()) { return false } - return JSONObject(this).getBoolean("success") + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("success").asBoolean } -fun String.toErrorMessage(): String { - val errorModel = Gson().fromJson( - this, object : TypeToken() {}.type - ) - return errorModel.message.toString() +fun String.getResponseMessage(): String { + if (this.isBlank()) { + return "" + } + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("message").asString } /** @@ -131,4 +132,9 @@ } else { "6" } +} + +fun String.isNumber(): Boolean { + val regex = Regex("[-+]?\\d+(\\.\\d+)?") + return this.matches(regex) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt new file mode 100644 index 0000000..8b78a3c --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt @@ -0,0 +1,31 @@ +package com.casic.electric.detector.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import androidx.fragment.app.Fragment +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} + +fun ViewGroup.initImmersionBar(fragment: Fragment, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(fragment) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(fragment.requireContext())) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = fragment.requireContext().getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt new file mode 100644 index 0000000..84c9cd9 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt @@ -0,0 +1,3 @@ +package com.casic.electric.detector.model + +data class CalculateResult(val angle: Int, val direction: String, val distance: Int) diff --git a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java b/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java deleted file mode 100644 index 1574393..0000000 --- a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.casic.electric.detector.model; - -public class ErrorMessageModel { - private int code; - private String data; - private String exceptionClazz; - private String message; - private boolean isSuccess; - - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public String getExceptionClazz() { - return exceptionClazz; - } - - public void setExceptionClazz(String exceptionClazz) { - this.exceptionClazz = exceptionClazz; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public boolean isSuccess() { - return isSuccess; - } - - public void setSuccess(boolean success) { - isSuccess = success; - } -} diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt index 950fb91..f590226 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt @@ -90,10 +90,25 @@ /** * 上传工单中标识器信息 + * info中的主键 */ @GET("/ems/rs/task/update-task-mark") suspend fun uploadMarker( - @Query("userName") userId: String, - @Query("taskDetailId") taskId: String, + @Query("taskDetailId") taskId: String ): String + + /** + * 新建自由巡检任务 + * */ + @GET("ems/rs/task/addAppTask") + suspend fun createFreeTask( + @Query("patrollerId") patrollerId: String, + @Query("description") description: String + ): String + + /** + * 上传自由巡检过程中发现的标识器 + * */ + @POST("ems/event/uploadAppMarker.do") + suspend fun uploadTaskMarker(@Body requestBody: RequestBody): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt index 6834fc5..7836b28 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt @@ -1,5 +1,6 @@ package com.casic.electric.detector.retrofit +import com.casic.electric.detector.extensions.reformat import com.casic.electric.detector.utils.LabelDataClass import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.SmallLabelDataClass @@ -15,43 +16,32 @@ object RetrofitServiceManager { + private fun createApi(): RetrofitService { + val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String + val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String + val httpConfig = "http://${serverIp}:${serverPort}" + return RetrofitFactory.createRetrofit(httpConfig) + } + /** * 登录 */ suspend fun login(account: String, password: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.login(account, password) + return createApi().login(account, password) } /** * 更新版本 * */ suspend fun getApplicationVersion(): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getApplicationVersion() + return createApi().getApplicationVersion() } /** * 获取标识器信息文件 */ suspend fun getMarkerFile(userId: String, companyId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getMarkerFile(userId, companyId) + return createApi().getMarkerFile(userId, companyId) } /** @@ -64,39 +54,21 @@ "application/json;charset=UTF-8".toMediaType() ) - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getLabelPicture(requestBody) + return createApi().getLabelPicture(requestBody) } /** * 获取巡检工单 */ suspend fun getTask(userName: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getTask(userName) + return createApi().getTask(userName) } /** * 提交工单 */ suspend fun uploadTask(userId: String, taskId: String?, state: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadTask(userId, taskId.toString(), state) + return createApi().uploadTask(userId, taskId.toString(), state) } /** @@ -164,27 +136,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installLabel(res, multiParts[0], multiParts[1], null) + createApi().installLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installLabel(res, multiParts[0], null, null) + createApi().installLabel(res, multiParts[0], null, null) } else -> { - api.installLabel(res, null, null, null) + createApi().installLabel(res, null, null, null) } } } @@ -230,27 +196,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], null) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installSmallLabel(res, multiParts[0], null, null) + createApi().installSmallLabel(res, multiParts[0], null, null) } else -> { - api.installSmallLabel(res, null, null, null) + createApi().installSmallLabel(res, null, null, null) } } } @@ -279,27 +239,23 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2]) + createApi().uploadEvent( + taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2] + ) } 2 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) } 1 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) } else -> { - api.uploadEvent(taskIdMap, eventMap, null, null, null) + createApi().uploadEvent(taskIdMap, eventMap, null, null, null) } } } @@ -307,13 +263,27 @@ /** * 上传工单中标识器信息 */ - suspend fun uploadMarker(userName: String, taskDetailId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadMarker(userName, taskDetailId) + suspend fun uploadMarker(taskDetailId: String): String { + return createApi().uploadMarker(taskDetailId) + } + + /** + * 上传工单中标识器信息 + */ + suspend fun createFreeTask(patrollerId: String, description: String): String { + return createApi().createFreeTask(patrollerId, description) + } + + /** + * 上传自由巡检过程中发现的标识器 + */ + suspend fun uploadTaskMarker(taskId: String, models: ArrayList): String { + val param = JsonObject() + param.addProperty("taskId", taskId) + param.addProperty("ids", models.reformat()) + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return createApi().uploadTaskMarker(requestBody) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java index 4aba809..45d5a2f 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java +++ b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java @@ -1,8 +1,10 @@ package com.casic.electric.detector.utils; -public class GpioManager { +import android.util.Log; +public class GpioManager { + private static final String TAG = "GpioManager"; private static final int MT6761 = 0; private int selected; private final MT6761Gpio mt6761; @@ -38,6 +40,7 @@ * 璁剧疆GPIO杈撳嚭楂� * *********************************************************************/ public void setGpioHigh(String gpio) { + Log.d(TAG, "setGpioHigh: 调高电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioHigh(); @@ -48,6 +51,7 @@ * 璁剧疆GPIO杈撳嚭浣� * *********************************************************************/ public void setGpioLow(String gpio) { + Log.d(TAG, "setGpioLow: 调低电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioLow(); diff --git a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt deleted file mode 100644 index c589c4b..0000000 --- a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.electric.detector.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt index 4de12f2..9356f9a 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt @@ -13,7 +13,7 @@ ) const val PERMISSIONS_CODE = 999 - const val RADIUS_SIZE = 100f //相距多少米才聚合,单位:米 + const val RADIUS_SIZE = 100 //相距多少米才聚合,单位:米 const val AUTO_SAVE = "AUTO_SAVE" const val USER_ACCOUNT = "USER_ACCOUNT" @@ -28,10 +28,21 @@ const val APP_AUTHORITY = "com.casic.electric.detector.fileprovider" val POPUP_TITLES = arrayOf("更新数据", "下载工单", "关于软件", "事件上报", "标识器补全") - var CONDITION_ARRAY = arrayOf("种类", "编号", "名称", "所属区域", "所属道路", "运检单位", "责任人", "建设时间", "标识器ID") + var CONDITION_ARRAY = arrayOf( + "种类", + "编号", + "名称", + "所属区域", + "所属道路", + "运检单位", + "责任人", + "建设时间", + "标识器ID" + ) var CONTENT_ARRAY = arrayOf("电缆井", "电缆通道", "配电房", "开关站", "台区", "杆塔") var OBJECT_MODE_ARRAY = arrayOf("直线井", "转弯井", "丁字井", "十字井", "其他") - var WELL_COVER_MATERIAL_ARRAY_1 = arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") + var WELL_COVER_MATERIAL_ARRAY_1 = + arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") var WELL_COVER_MATERIAL_ARRAY_2 = arrayOf("水泥杆", "钢管杆", "铁塔", "其他") var CABINET_TYPE_ARRAY = arrayOf("无", "SM6", "SAFE", "RM6", "XGN15", "固体柜") var PIPE_MATERIAL_ARRAY = arrayOf("无", "PVC管", "波纹管", "镀锌钢管") @@ -42,7 +53,16 @@ var CROSS_PIPE_STATE_ARRAY = booleanArrayOf(false, false, false, false, false, false, false) var POINT_TYPE_ARRAY = arrayOf("管线", "管线附属物", "管线特征管点", "交叉穿越点") - var SPINNER_ARRAY = arrayOf("标识器ID", "所属区域", "所属线路", "所属道路", "权属单位", "安装部门", "安装时间", "备注") + var SPINNER_ARRAY = arrayOf( + "标识器ID", + "所属区域", + "所属线路", + "所属道路", + "权属单位", + "安装部门", + "安装时间", + "备注" + ) var DOWN_PIPE_TYPE_ARRAY = arrayOf("热力", "燃气", "供水", "电力", "通信") var BURY_METHOD_ARRAY = arrayOf("直埋", "圆管", "管块", "管沟", "架空") var COLOR_ARRAY = arrayOf("蓝色", "橙色", "红色", "黑色", "紫色", "黄色", "绿色") diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt index 4f0f2c7..61e55f6 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt @@ -14,14 +14,16 @@ import com.casic.electric.detector.callback.IAddressListener import com.casic.electric.detector.callback.ILocationListener -object LocationHub { - private const val kTag = "LocationHub" +class LocationHub constructor(context: Context) { - fun getCurrentLocation(context: Context, listener: ILocationListener) { - val locationClient = AMapLocationClient(context) + private val kTag = "LocationHub" + private val locationClient by lazy { AMapLocationClient(context) } + private val codeSearch by lazy { GeocodeSearch(context) } + + fun getCurrentLocation(isOnceLocation: Boolean, listener: ILocationListener) { val locationOption = AMapLocationClientOption() locationOption.locationMode = AMapLocationClientOption.AMapLocationMode.Hight_Accuracy - locationOption.isOnceLocation = true + locationOption.isOnceLocation = isOnceLocation locationClient.setLocationOption(locationOption) locationClient.setLocationListener { if (it.errorCode == 0) { @@ -36,9 +38,8 @@ locationClient.startLocation() } - fun antiCodingLocation(context: Context, location: Location, listener: IAddressListener) { + fun antiCodingLocation(location: Location, listener: IAddressListener) { try { - val codeSearch = GeocodeSearch(context) // 第一个参数表示一个LatLonPoint,第二参数表示范围多少米,第三个参数表示是火系坐标系还是GPS原生坐标系 val query = RegeocodeQuery( LatLonPoint(location.latitude, location.longitude), 10f, GeocodeSearch.AMAP @@ -55,4 +56,8 @@ e.printStackTrace() } } + + fun stopLocation() { + locationClient.stopLocation() + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt b/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt index aa1bdeb..e3d3289 100644 --- a/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt @@ -1,7 +1,6 @@ package com.casic.electric.detector.view import android.content.Context -import android.graphics.Color import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -12,10 +11,10 @@ import com.bumptech.glide.Glide import com.casic.electric.detector.R import com.casic.electric.detector.databinding.ActivityBigImageBinding +import com.casic.electric.detector.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class BigImageActivity : KotlinBaseActivity() { @@ -24,20 +23,12 @@ } override fun setupTopBarLayout() { - ImmerseStatusBarUtil.setColor(this, Color.BLACK) + binding.rootView.initImmersionBar(this, false, R.color.black) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - val index: Int = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return @@ -62,6 +53,14 @@ }) } + override fun observeRequestState() { + + } + + override fun initEvent() { + + } + inner class BigImageAdapter( private val context: Context, private val data: ArrayList ) : PagerAdapter() { diff --git a/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt b/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt index d3a89ca..6510104 100644 --- a/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt @@ -29,15 +29,15 @@ import com.casic.electric.detector.extensions.* import com.casic.electric.detector.utils.* import com.casic.electric.detector.vm.TaskViewModel -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia import com.luck.picture.lib.interfaces.OnResultCallbackListener import com.pengxh.kt.lite.extensions.* +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -53,7 +53,8 @@ private val context: Context = this@InstallLabelActivity private val gpioManager by lazy { GpioManager() } private val calendar by lazy { Calendar.getInstance() } - private val realPaths: ArrayList = ArrayList() //真实图片路径 + private val locationHub by lazy { LocationHub(this) } + private val realPaths = ArrayList() //真实图片路径 private var soundResId = 0 private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var soundPool: SoundPool @@ -67,12 +68,6 @@ override fun setupTopBarLayout() { binding.titleInclude.titleView.text = "安装新标识器" binding.titleInclude.titleView.setTextColor(R.color.themeColor.convertColor(this)) - - ImmersionBar.with(this) - .statusBarDarkFont(true) - .statusBarColor(R.color.mainBackground) - .init() - initLayoutImmersionBar(binding.rootView) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -126,7 +121,7 @@ binding.markerAttrInclude.remarkView3.setText("remarkView3".getDefaultValue()) //初始化图片九宫格 - imageAdapter = EditableImageAdapter(this, 3, 3f) + imageAdapter = EditableImageAdapter(this, 3, 3) binding.cameraInclude.addImageRecyclerView.adapter = imageAdapter taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] @@ -332,7 +327,7 @@ binding.markerAttrInclude.installTimeView.text = System.currentTimeMillis().timestampToCompleteDate() - LocationHub.getCurrentLocation(this, object : ILocationListener { + locationHub.getCurrentLocation(true, object : ILocationListener { override fun onAMapLocationGet(location: AMapLocation?) { if (location != null) { binding.markerAttrInclude.lngView.text = location.longitude.toString() @@ -518,8 +513,8 @@ weakReferenceHandler.postDelayed({ try { // 发送读标识器或搜索信号 - outputStream?.write("2".toByteArray()) - outputStream?.flush() + out.write("2".toByteArray()) + out.flush() } catch (e: IOException) { e.printStackTrace() } @@ -527,7 +522,7 @@ } } - override fun onDataReceived(buffer: ByteArray?, size: Int) { + override fun onDataReceived(buffer: ByteArray) { Log.d(kTag, "onDataReceived => " + buffer.contentToString()) if (buffer != null) { val message = weakReferenceHandler.obtainMessage() diff --git a/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt b/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt index 5bc2ac8..286bf4a 100644 --- a/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt @@ -24,7 +24,6 @@ import com.casic.electric.detector.extensions.* import com.casic.electric.detector.utils.* import com.casic.electric.detector.vm.TaskViewModel -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -33,9 +32,10 @@ import com.pengxh.kt.lite.extensions.isNetworkConnected import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -65,12 +65,6 @@ override fun setupTopBarLayout() { binding.titleInclude.titleView.text = "安装新电子标签" binding.titleInclude.titleView.setTextColor(R.color.themeColor.convertColor(this)) - - ImmersionBar.with(this) - .statusBarDarkFont(true) - .statusBarColor(R.color.mainBackground) - .init() - initLayoutImmersionBar(binding.rootView) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -103,7 +97,7 @@ binding.objectAttrInclude.objectRemarkView3.setText("objectRemarkView3".getDefaultValue()) //初始化图片九宫格 - imageAdapter = EditableImageAdapter(this, 3, 3f) + imageAdapter = EditableImageAdapter(this, 3, 3) binding.cameraInclude.addImageRecyclerView.adapter = imageAdapter taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] @@ -308,8 +302,8 @@ weakReferenceHandler.postDelayed({ try { // 发送读标识器或搜索信号 - outputStream?.write("2".toByteArray()) - outputStream?.flush() + out.write("2".toByteArray()) + out.flush() } catch (e: IOException) { e.printStackTrace() } @@ -317,7 +311,7 @@ } } - override fun onDataReceived(buffer: ByteArray?, size: Int) { + override fun onDataReceived(buffer: ByteArray) { if (buffer != null) { val message = weakReferenceHandler.obtainMessage() message.what = 2023081702 diff --git a/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt b/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt index 44d56ef..9c98b5f 100644 --- a/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt @@ -1,36 +1,29 @@ package com.casic.electric.detector.view import android.os.Bundle -import android.util.Log import androidx.lifecycle.ViewModelProvider import com.amap.api.navi.NaviSetting import com.casic.electric.detector.databinding.ActivityLoginBinding -import com.casic.electric.detector.extensions.initLayoutImmersionBar -import com.casic.electric.detector.utils.GpioManager -import com.casic.electric.detector.utils.LoadingDialogHub import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.vm.UserViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.getScreenHeight -import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog class LoginActivity : KotlinBaseActivity() { private val kTag = "LoginActivity" private lateinit var userViewModel: UserViewModel - private val gpioManager by lazy { GpioManager() } override fun initViewBinding(): ActivityLoginBinding { return ActivityLoginBinding.inflate(layoutInflater) } override fun initOnCreate(savedInstanceState: Bundle?) { - gpioManager.setGpioLow("18") //先把导航隐私政策声明,后面导航会用到 NaviSetting.updatePrivacyShow(this, true, true) NaviSetting.updatePrivacyAgree(this, true) @@ -60,11 +53,8 @@ val serversIp = binding.serversIpView.text.toString() val serversPort = binding.serversPortView.text.toString() if (account.isBlank() || password.isBlank() || serversIp.isBlank() || serversPort.isBlank()) { - AlertMessageDialog.Builder() - .setContext(this) - .setTitle("账号登录") - .setMessage("信息不能为空哦!") - .setPositiveButton("知道了") + AlertMessageDialog.Builder().setContext(this).setTitle("账号登录") + .setMessage("信息不能为空哦!").setPositiveButton("知道了") .setOnDialogButtonClickListener(object : AlertMessageDialog.OnDialogButtonClickListener { override fun onConfirmClick() { @@ -102,9 +92,6 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(true).init() - initLayoutImmersionBar(binding.rootView) - - Log.d(kTag, "setupTopBarLayout => [${getScreenWidth()}, ${getScreenHeight()}]") } override fun onResume() { diff --git a/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt b/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt index 36a8d55..a0a4aac 100644 --- a/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt @@ -1,15 +1,21 @@ package com.casic.electric.detector.view +import android.annotation.SuppressLint import android.app.AlertDialog +import android.app.Dialog import android.content.Context -import android.content.Intent import android.graphics.Color import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable +import android.media.AudioAttributes +import android.media.SoundPool import android.os.Bundle -import android.os.PowerManager -import android.provider.Settings +import android.os.CountDownTimer +import android.util.Log import android.view.KeyEvent +import android.view.View +import android.view.animation.Animation +import android.view.animation.RotateAnimation import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import com.amap.api.location.AMapLocation @@ -21,6 +27,8 @@ import com.amap.api.maps.model.LatLngBounds import com.amap.api.maps.model.MyLocationStyle import com.casic.electric.detector.R +import com.casic.electric.detector.adapter.EditableImageAdapter +import com.casic.electric.detector.base.SerialPortActivity import com.casic.electric.detector.bean.LabelBean import com.casic.electric.detector.bean.SmallLabelBean import com.casic.electric.detector.bean.TaskBean @@ -29,83 +37,109 @@ import com.casic.electric.detector.cluster.ClusterOverlay import com.casic.electric.detector.cluster.RegionItem import com.casic.electric.detector.databinding.ActivityMainBinding +import com.casic.electric.detector.databinding.DialogInstallMarkerBinding +import com.casic.electric.detector.databinding.DialogInstallSmallMarkerBinding +import com.casic.electric.detector.databinding.DialogSearchMarkerBinding import com.casic.electric.detector.extensions.appendExcelDownloadUrl import com.casic.electric.detector.extensions.drawCircle -import com.casic.electric.detector.extensions.initLayoutImmersionBar +import com.casic.electric.detector.extensions.hexToString +import com.casic.electric.detector.extensions.initImmersionBar +import com.casic.electric.detector.extensions.isNumber +import com.casic.electric.detector.extensions.toHex import com.casic.electric.detector.utils.DataBaseManager import com.casic.electric.detector.utils.ExcelHub -import com.casic.electric.detector.utils.LoadingDialogHub +import com.casic.electric.detector.utils.GpioManager import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.LocationHub import com.casic.electric.detector.utils.RouteOnMap import com.casic.electric.detector.vm.TaskViewModel import com.casic.electric.detector.widgets.QueryMarkerDialog import com.casic.electric.detector.widgets.SamplePopupWindow -import com.gyf.immersionbar.ImmersionBar -import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.callback.OnDownloadListener +import com.google.gson.Gson +import com.pengxh.kt.lite.extensions.binding import com.pengxh.kt.lite.extensions.createDownloadFileDir -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.dp2px +import com.pengxh.kt.lite.extensions.initDialogLayoutParams import com.pengxh.kt.lite.extensions.isNetworkConnected import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.toJson +import com.pengxh.kt.lite.utils.FileDownloadManager +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog +import com.pengxh.kt.lite.widget.dialog.AlertInputDialog +import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File +import java.text.DecimalFormat +import java.util.Calendar +import java.util.Timer +import java.util.TimerTask -class MainActivity : KotlinBaseActivity() { +@SuppressLint("all") +class MainActivity : SerialPortActivity() { private val kTag = "MainActivity" - private val context: Context = this@MainActivity + private val context = this@MainActivity + private val gpioManager by lazy { GpioManager() } private val samplePopupWindow by lazy { SamplePopupWindow(this) } + private val gson by lazy { Gson() } + private val locationHub by lazy { LocationHub(this) } + private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } + private val backDrawables by lazy { HashMap() } + private val installMarkerDialog by lazy { InstallMarkerDialog(this) } + private val installSmallMarkerDialog by lazy { InstallSmallMarkerDialog(this) } + private val searchDialog by lazy { SearchMarkerDialog(this) } private var clickTime: Long = 0 - private lateinit var wakeLock: PowerManager.WakeLock - private lateinit var aMap: AMap - private lateinit var taskViewModel: TaskViewModel - private lateinit var taskBean: TaskBean - private var latitude: Double = 0.0 - private var longitude: Double = 0.0 private var labels = ArrayList() private var smallLabels = ArrayList() private var clusterOverlay: ClusterOverlay? = null - private val backDrawables = HashMap() - private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } + private var latitude: Double = 0.0 + private var longitude: Double = 0.0 + private var isFreeTask = false + private var ids = ArrayList() + private var signalTask: TimerTask? = null + private var searchMarkerTimer: Timer? = null + private lateinit var aMap: AMap + private lateinit var taskBean: TaskBean + private lateinit var taskId: String + + /***inner class 需要用到*****start*/ + private val taskViewModel by lazy { ViewModelProvider(this)[TaskViewModel::class.java] } + 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 var soundResourceId = 0 + private var slowSoundResourceId = 0 + private var fastSoundResourceId = 0 + + /***inner class 需要用到*****end*/ override fun initViewBinding(): ActivityMainBinding { return ActivityMainBinding.inflate(layoutInflater) } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).statusBarColor(R.color.themeColor).init() - initLayoutImmersionBar(binding.rootView) - } - - override fun observeRequestState() { - + binding.rootView.initImmersionBar(this, false, R.color.themeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { - val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager - wakeLock = powerManager.run { - newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this@MainActivity.localClassName).apply { - acquire(60 * 60 * 1000L) - } - } + soundResourceId = soundPool.load(this, R.raw.ring3, 1) + slowSoundResourceId = soundPool.load(this, R.raw.ring4, 1) + fastSoundResourceId = soundPool.load(this, R.raw.ring2, 1) + //地图初始化 initMapConfig(savedInstanceState) samplePopupWindow.setPopupMenuItem(LocaleConstant.POPUP_TITLES) samplePopupWindow.setBackgroundDrawable(null) - taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] + //task网络请求监听 taskViewModel.markerFileResult.observe(this) { if (it.success == "true") { //清空之前的数据 @@ -122,11 +156,13 @@ val smallLabelDownloadUrl = urlArray[1].appendExcelDownloadUrl() //下载标识器 - labelDownloadUrl.downloadFile( - createDownloadFileDir().toString(), object : OnDownloadListener { - override fun onDownloadEnd(file: File?) { + FileDownloadManager.Builder().setDownloadFileSource(labelDownloadUrl) + .setFileSuffix("xls").setFileSaveDirectory(createDownloadFileDir()) + .setOnFileDownloadListener(object : + FileDownloadManager.OnFileDownloadListener { + override fun onDownloadEnd(file: File) { lifecycleScope.launch { - labels = ExcelHub.readLabel(file?.absolutePath) + labels = ExcelHub.readLabel(file.absolutePath) withContext(Dispatchers.IO) { labels.forEach { label -> DataBaseManager.get.insertLabel(label) @@ -137,21 +173,23 @@ } } - override fun onDownloadStart(totalBytes: Long) { + override fun onFailure(throwable: Throwable) { } - override fun onProgressChanged(currentBytes: Long) { + override fun onProgressChanged(progress: Int) { } - }) + }).build().start() //下载附属标识器 - smallLabelDownloadUrl.downloadFile( - createDownloadFileDir().toString(), object : OnDownloadListener { - override fun onDownloadEnd(file: File?) { + FileDownloadManager.Builder().setDownloadFileSource(smallLabelDownloadUrl) + .setFileSuffix("xls").setFileSaveDirectory(createDownloadFileDir()) + .setOnFileDownloadListener(object : + FileDownloadManager.OnFileDownloadListener { + override fun onDownloadEnd(file: File) { lifecycleScope.launch { - smallLabels = ExcelHub.readSmallLabel(file?.absolutePath) + smallLabels = ExcelHub.readSmallLabel(file.absolutePath) withContext(Dispatchers.IO) { smallLabels.forEach { label -> DataBaseManager.get.insertSmallLabel(label) @@ -160,14 +198,14 @@ } } - override fun onDownloadStart(totalBytes: Long) { + override fun onFailure(throwable: Throwable) { } - override fun onProgressChanged(currentBytes: Long) { + override fun onProgressChanged(progress: Int) { } - }) + }).build().start() } } } @@ -175,11 +213,8 @@ // if (it.success == "true") { // //清空之前的数据 // DataBaseManager.get.clearTasks() -// AlertMessageDialog.Builder() -// .setContext(this) -// .setTitle("温馨提示") -// .setMessage("您有${it.message.size}个新任务!") -// .setPositiveButton("知道了") +// AlertMessageDialog.Builder().setContext(this).setTitle("温馨提示") +// .setMessage("您有${it.message.size}个新任务!").setPositiveButton("知道了") // .setOnDialogButtonClickListener(object : // AlertMessageDialog.OnDialogButtonClickListener { // override fun onConfirmClick() { @@ -188,19 +223,24 @@ // }).build().show() // } // } + taskViewModel.freeTaskResult.observe(this) { taskId = it } + taskViewModel.uploadTaskMarkerResult.observe(this) { + "自由巡检任务已完成".show(this) + ids.clear() + } } override fun initEvent() { binding.rightImageView.setOnClickListener { - CoroutineScope(Dispatchers.Main).launch { + lifecycleScope.launch(Dispatchers.Main) { val labels = withContext(Dispatchers.IO) { DataBaseManager.get.queryLabelById("0") } if (labels.isNotEmpty()) { samplePopupWindow.setShowPosition(4) } - val x = binding.rightImageView.width - samplePopupWindow.width - 1f.dp2px(context) - samplePopupWindow.showAsDropDown(binding.rightImageView, x, 1f.dp2px(context)) + val x = binding.rightImageView.width - samplePopupWindow.width - 1.dp2px(context) + samplePopupWindow.showAsDropDown(binding.rightImageView, x, 1.dp2px(context)) } } @@ -219,35 +259,33 @@ //安装。上传,然后存入本地库 binding.installButton.setOnClickListener { - AlertControlDialog.Builder() - .setContext(context) - .setTitle("提示") - .setMessage("请选择安装对象") - .setPositiveButton("标识器") - .setNegativeButton("电子标签") - .setOnDialogButtonClickListener(object : + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("请选择安装对象").setPositiveButton("标识器") + .setNegativeButton("电子标签").setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { //标识器 - navigatePageTo() + /** + * 改为Dialog方式,避免频繁打开/关闭串口 + * */ + installMarkerDialog.show() } override fun onCancelClick() { //电子标签 - navigatePageTo() + /** + * 改为Dialog方式,避免频繁打开/关闭串口 + * */ + installSmallMarkerDialog.show() } }).build().show() } //查看 binding.viewButton.setOnClickListener { - QueryMarkerDialog.Builder() - .setContext(this) - .setTitle("查看标识器") - .setConditionArray(LocaleConstant.CONDITION_ARRAY) - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : + QueryMarkerDialog.Builder().setContext(this).setTitle("查看标识器") + .setConditionArray(LocaleConstant.CONDITION_ARRAY).setNegativeButton("取消") + .setPositiveButton("确定").setOnDialogButtonClickListener(object : QueryMarkerDialog.OnDialogButtonClickListener { override fun onConfirmClick( selectedCondition: String, vararg contentValue: String @@ -310,30 +348,25 @@ // arrayList.add("任务${index + 1}:${taskBean.taskId},${taskBean.desc}") // } // -// BottomActionSheet.Builder() -// .setContext(this) -// .setItemTextColor(Color.BLUE) +// BottomActionSheet.Builder().setContext(this).setItemTextColor(Color.BLUE) // .setActionItemTitle(arrayList) // .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { // override fun onActionItemClick(position: Int) { // val taskBean = task[position] // SaveKeyValues.putValue(LocaleConstant.TASK_ID, taskBean.taskId) -// AlertControlDialog.Builder() -// .setContext(context) -// .setTitle("提示") -// .setMessage("请选择操作方式") -// .setPositiveButton("执行工单") +// AlertControlDialog.Builder().setContext(context).setTitle("提示") +// .setMessage("请选择操作方式").setPositiveButton("执行工单") // .setNegativeButton("提交工单") // .setOnDialogButtonClickListener(object : // AlertControlDialog.OnDialogButtonClickListener { // override fun onConfirmClick() { // detectRedrawGraphic(taskBean.taskId) +// +// val latLng = LatLng( +// taskBean.lat.toDouble(), taskBean.lng.toDouble() +// ) // aMap.moveCamera( -// CameraUpdateFactory.newLatLngZoom( -// LatLng( -// taskBean.lat.toDouble(), taskBean.lng.toDouble() -// ), 15f -// ) +// CameraUpdateFactory.newLatLngZoom(latLng, 16f) // ) // uploadTask(taskBean.taskId, "1") // } @@ -345,15 +378,12 @@ // } // }).build().show() // } else { -// AlertMessageDialog.Builder() -// .setContext(this) -// .setTitle("温馨提示") -// .setMessage("现有任务已完成,请点击右上角菜单按钮下载新工单!") -// .setPositiveButton("知道了") -// .setOnDialogButtonClickListener(object : +// AlertMessageDialog.Builder().setContext(this).setTitle("温馨提示") +// .setMessage("现有任务已完成,请点击右上角菜单下载新工单或者开始自由巡检") +// .setPositiveButton("知道了").setOnDialogButtonClickListener(object : // AlertMessageDialog.OnDialogButtonClickListener { // override fun onConfirmClick() { -// +// startFreeTask() // } // }).build().show() // } @@ -361,7 +391,118 @@ //探测 binding.detectionButton.setOnClickListener { -// navigatePageTo() + /** + * 改为Dialog方式,避免频繁打开/关闭串口 + * */ + searchDialog.show() + } + + //自由巡检 + binding.stopFreeTaskButton.setOnLongClickListener { + AlertMessageDialog.Builder().setContext(this).setTitle("温馨提示") + .setMessage("是否确定结束此次自由巡检任务?").setPositiveButton("是") + .setOnDialogButtonClickListener(object : + AlertMessageDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + isFreeTask = false + soundPool.autoPause() + + //降低串口电位 + gpioManager.setGpioLow("18") + + taskViewModel.uploadTaskMarker(taskId, ids) + binding.stopFreeTaskButton.visibility = View.GONE + } + }).build().show() + true + } + } + + private fun startFreeTask() { + AlertInputDialog.Builder().setContext(this).setTitle("新建自由巡检任务") + .setHintMessage("请输入自由巡检任务简要描述").setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : AlertInputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String + taskViewModel.createFreeTask(userId, value) + + //调高串口电位 + gpioManager.setGpioHigh("18") + + soundPool.play(soundResourceId, 1f, 1f, 0, -1, 1f) + isFreeTask = true + //自由巡检 + signalTask = object : TimerTask() { + override fun run() { + out.write('2'.code) + out.flush() + } + } + searchMarkerTimer = Timer() + searchMarkerTimer?.apply { + schedule(signalTask, 0, 100) + } + + binding.stopFreeTaskButton.visibility = View.VISIBLE + } + + override fun onCancelClick() {} + }).build().show() + } + + override fun onDataReceived(buffer: ByteArray) { + val hex = buffer.toHex() + Log.d(kTag, "$kTag => $hex") + if (searchDialog.isDetectMarker) { + searchDialog.bindingValue(hex) +// } else if (installMarkerDialog.isReadMarker) { +// val markerId = hex.take(20).hexToString() +// if (markerId.isNumber()) { +// installMarkerDialog.bindingValue(markerId) +// } +// } else if (installSmallMarkerDialog.isReadMarker) { +// val markerId = hex.take(20).hexToString() +// if (markerId.isNumber()) { +// installSmallMarkerDialog.bindingValue(markerId) +// } + } else if (isFreeTask) { + val markerId = hex.take(20).hexToString() + if (markerId.isNumber()) { + "标识器${markerId}已探测".show(this) + ids.add(markerId) + } + } + } + + override fun observeRequestState() { + taskViewModel.loadState.observe(this) { + when (it) { + LoadState.Loading -> { + if (installMarkerDialog.isInstallMarker || installSmallMarkerDialog.isInstallMarker) { + LoadingDialogHub.show(this, "标识器安装中,请稍后...") + } else if (searchDialog.isDetectMarker) { + searchDialog.taskBean?.apply { + "标识器${this.markerId}已探测!".show(context) +// DataBaseManager.get.updateTaskLabel(this) + } + } else { + LoadingDialogHub.show(this, "提交工单中,请稍后") + } + } + + else -> { + if (installMarkerDialog.isInstallMarker) { + installMarkerDialog.dismiss() + installMarkerDialog.isInstallMarker = false + } else if (installSmallMarkerDialog.isInstallMarker) { + installSmallMarkerDialog.dismiss() + installSmallMarkerDialog.isInstallMarker = false + } + LoadingDialogHub.dismiss() + } + } + detectRedrawGraphic(taskBean.taskId) } } @@ -375,6 +516,7 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜 //显示定位小蓝点 val locationStyle = MyLocationStyle() locationStyle.interval(2000) @@ -387,7 +529,7 @@ longitude = it.longitude latitude = it.latitude //经纬度逆编码 - LocationHub.antiCodingLocation(context, it) { address -> + locationHub.antiCodingLocation(it) { address -> binding.currentLocationView.text = address } } @@ -417,7 +559,7 @@ } private fun moveToCurrentLocation() { - LocationHub.getCurrentLocation(this, object : ILocationListener { + locationHub.getCurrentLocation(true, object : ILocationListener { override fun onAMapLocationGet(location: AMapLocation?) { if (location != null) { aMap.moveCamera( @@ -432,46 +574,35 @@ }) } - //更新数据 - private fun updateLabels() { - AlertControlDialog.Builder() - .setContext(this) - .setTitle("提示") - .setMessage("是否更新数据?") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onConfirmClick() { - if (isNetworkConnected()) { - val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") - val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") - - LoadingDialogHub.show(this@MainActivity, "获取标识器信息中,请稍后") - //TODO 设计如此,都传companyId - taskViewModel.getMarkerFile(companyId.toString(), companyId.toString()) - } else { - NoNetworkDialog.Builder() - .setContext(context) - .setOnDialogButtonClickListener(object : - NoNetworkDialog.OnDialogButtonClickListener { - override fun onButtonClick() { - val intent = Intent(Settings.ACTION_SETTINGS) - startActivity(intent) - } - }).build().show() - } - } - - override fun onCancelClick() { - - } - }).build().show() - } +// private fun saveTaskInformation(it: TaskModel) { +// val userName = SaveKeyValues.getValue(LocaleConstant.USER_NAME, "") as String +// if (it.message.size > 0) { +// it.message.forEach { messageModel -> +// val count = DataBaseManager.get.countTaskById(messageModel.id.toString()) +// if (count == 0) { +// messageModel.taskDetailInfos.forEach { info -> +// DataBaseManager.get.insertTaskInformation( +// userName, +// messageModel.description, +// info.taskId.toString(), +// info.id.toString(), +// info.markerId.toString(), +// info.markerIdReal.toString(), +// info.longitude.toString(), +// info.latitude.toString(), +// messageModel.status +// ) +// } +// } +// } +// "工单下载成功!".show(context) +// } +// } private fun showLabelsOnMap() { clusterOverlay?.onDestroy() val clusterItems = ArrayList() + labels.forEach { val latLng = LatLng(it.latitude.toDouble(), it.longitude.toDouble(), false) val regionItem = RegionItem(latLng, it.markerId.toString()) @@ -480,7 +611,7 @@ clusterOverlay = ClusterOverlay(context, aMap, clusterItems, regionRadius) clusterOverlay?.setClusterRender { clusterNum -> - val radius = 80f.dp2px(context) + val radius = 80.dp2px(context) if (clusterNum == 0) { var bitmapDrawable = backDrawables[0] if (bitmapDrawable == null) { @@ -546,9 +677,7 @@ val latLngBounds = builder.build() aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 0)) - BottomActionSheet.Builder() - .setContext(this) - .setItemTextColor(Color.BLUE) + BottomActionSheet.Builder().setContext(this).setItemTextColor(Color.BLUE) .setActionItemTitle(listOf("标识器信息", "附属电子标签信息", "到这里去")) .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { override fun onActionItemClick(position: Int) { @@ -578,12 +707,7 @@ showElectricMarkers(electricMarkers) } - 2 -> { - RouteOnMap.startNavigation( - context, item.tag, - LatLng(item.position.latitude, item.position.longitude) - ) - } + 2 -> RouteOnMap.startNavigation(context, item.tag, latLng) } } }).build().show() @@ -591,14 +715,74 @@ } private fun showElectricMarkers(markers: ArrayList) { - AlertDialog.Builder(context) - .setIcon(R.mipmap.ic_launcher) - .setTitle("电子标签列表") + AlertDialog.Builder(context).setIcon(R.mipmap.ic_launcher).setTitle("电子标签列表") .setSingleChoiceItems(markers.toTypedArray(), -1) { _, which -> navigatePageTo(markers[which]) }.show() } + private fun detectRedrawGraphic(taskId: String) { +// val tasks = DataBaseManager.get.queryTaskById(taskId) +// if (tasks.isNotEmpty()) { +// tasks.forEach { +// val latLng = LatLng(it.lat.toDouble(), it.lng.toDouble()) +// val otMarkerOptions = MarkerOptions() +// otMarkerOptions.position(latLng) +// otMarkerOptions.visible(true) // 设置可见 +// if (it.state == "未开始") { +// otMarkerOptions.icon( +// BitmapDescriptorFactory.fromBitmap( +// BitmapFactory.decodeResource(resources, R.mipmap.label_red1) +// ) +// ).period(99).title("工单标识器").snippet(it.markerId) +// } else { +// otMarkerOptions.icon( +// BitmapDescriptorFactory.fromBitmap( +// BitmapFactory.decodeResource(resources, R.mipmap.label_blue1) +// ) +// ).period(99).title("工单标识器").snippet(it.markerId) +// } +// aMap.addMarker(otMarkerOptions) +// } +// } + showLabelsOnMap() + } + + private fun uploadTask(taskId: String?, state: String) { + if (isNetworkConnected()) { + val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String + taskViewModel.uploadTask(userId, taskId, state) + } else { + "网络连接已断开,请检查".show(this) + } + } + + //更新数据 + private fun updateLabels() { + AlertControlDialog.Builder().setContext(this).setTitle("提示").setMessage("是否更新数据?") + .setNegativeButton("取消").setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + if (isNetworkConnected()) { + val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") + + LoadingDialogHub.show(this@MainActivity, "获取标识器信息中,请稍后") + /** + * 后台设计如此,都传companyId + * */ + taskViewModel.getMarkerFile(companyId.toString(), companyId.toString()) + } else { + "网络连接已断开,请检查".show(context) + } + } + + override fun onCancelClick() { + + } + }).build().show() + } + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { return if (keyCode == KeyEvent.KEYCODE_BACK) { if (System.currentTimeMillis() - clickTime > 2000) { @@ -643,8 +827,270 @@ } override fun onDestroy() { - wakeLock.release() super.onDestroy() binding.mapView.onDestroy() + signalTask?.cancel() + searchMarkerTimer?.cancel() + soundPool.release() + locationHub.stopLocation() + //降低串口电位 + gpioManager.setGpioLow("18") + } + + /**安装标识器对话框******************************************************************************/ + inner class InstallMarkerDialog(context: Context) : Dialog(context) { + + private val binding: DialogInstallMarkerBinding by binding() + private val calendar by lazy { Calendar.getInstance() } + private val realPaths = ArrayList() //真实图片路径 + private lateinit var imageAdapter: EditableImageAdapter + + var isReadMarker = false + var isInstallMarker = false + } + + /**安装小标签对话框******************************************************************************/ + inner class InstallSmallMarkerDialog(context: Context) : Dialog(context) { + + private val binding: DialogInstallSmallMarkerBinding by binding() + private val calendar by lazy { Calendar.getInstance() } + private val realPaths = ArrayList() //真实图片路径 + private lateinit var imageAdapter: EditableImageAdapter + + var isReadMarker = false + var isInstallMarker = false + } + + /**探测标识器对话框******************************************************************************/ + inner class SearchMarkerDialog(context: Context) : Dialog(context) { + + private val binding: DialogSearchMarkerBinding by binding() + private val decimal by lazy { DecimalFormat("0.0") } + private val degreeCache by lazy { HashMap() } + private var isPlaying = false + private var markerId = "" + private lateinit var searchMarkerTimer: Timer + private lateinit var signalTask: TimerTask + private lateinit var energyTask: TimerTask + private lateinit var countDownTimer: CountDownTimer + + var isDetectMarker = false + var taskBean: TaskBean? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.initDialogLayoutParams(1f) + binding.depthButton.setOnClickListener { + signalTask.cancel() + energyTask.cancel() + searchMarkerTimer.cancel() + + out.write('3'.code) +// val result = DataBaseManager.get.queryLabelById(markerId) +// if (result.isNotEmpty()) { +// val tag = when (result.first().identifierType) { +// "EM30" -> '7' +// "EM50" -> '8' +// "EM14" -> '9' +// else -> '1' +// } +// if (tag == '1') { +// "此标识器无法读取埋深!".show(context) +// } else { +// // 发送读取标识器埋设深度指令 +// LoadingDialogHub.show(this@MainActivity, "正在测距,请稍后...") +// out.write(tag.code) +// out.flush() +// countDownTimer = object : CountDownTimer(15 * 1000, 1000) { +// override fun onTick(millisUntilFinished: Long) { +// +// } +// +// override fun onFinish() { +// LoadingDialogHub.dismiss() +// "探测此标识器深度超时,请重试".show(context) +// initTimer() +// } +// } +// countDownTimer.start() +// } +// } else { +// "标识器未安装,安装成功后才可读取埋深!".show(context) +// } + } + + binding.markerInfoButton.setOnClickListener { + //查库 + val result = DataBaseManager.get.queryLabelById(markerId) + if (result.isNotEmpty()) { +// context.navigatePageTo(result.first().toJson()) + } else { +// context.navigatePageTo(markerId) + } + } + } + + override fun onStart() { + super.onStart() + //调高串口电位 + gpioManager.setGpioHigh("18") + + initTimer() + + isDetectMarker = true + + //角度 + degreeCache["lastDegree"] = 0f + } + + fun bindingValue(hex: String) { + if (hex.startsWith("4E")) { + try { + //4E转为String为N,代表能量值 + //用能量值转动表盘 + val energyResponse = hex.take(10).hexToString() + val energy = energyResponse.substring(1).toInt() + if (energy >= 4000) { + isPlaying = if (!isPlaying) { + soundPool.play(fastSoundResourceId, 1f, 1f, 0, 0, 1f) + true + } else { + soundPool.pause(fastSoundResourceId) + false + } + } else { + isPlaying = if (!isPlaying) { + soundPool.play(slowSoundResourceId, 1f, 1f, 0, 0, 1f) + true + } else { + soundPool.pause(slowSoundResourceId) + false + } + } + + binding.resultTextView.text = "信号能量值:${energyResponse}" + + //转换为转动的角度 + val degree = (energy.toFloat() / (50 * 100)) * 180 + binding.energyValueView.text = decimal.format(degree) + + degreeCache["lastDegree"]?.apply { + val animation = RotateAnimation( + this, degree, + Animation.RELATIVE_TO_SELF, 0.5f, + Animation.RELATIVE_TO_SELF, 0.5f + ) + animation.duration = 0 + animation.fillAfter = true + binding.needleView.startAnimation(animation) + } + + //保存旋转后的角度 + degreeCache["lastDegree"] = degree + + if (energy <= 700) {//18° + binding.energyTipsView.text = "标识器信号较弱,可能距离较远" + binding.energyTipsView.setTextColor(Color.parseColor("#8D1717")) + binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_red) + + binding.depthButton.isEnabled = false + binding.depthButton.setTextColor(Color.parseColor("#CCCCCC")) + binding.depthButton.setBackgroundResource(R.mipmap.left_button_disable) + binding.markerInfoButton.isEnabled = false + binding.markerInfoButton.setTextColor(Color.parseColor("#CCCCCC")) + binding.markerInfoButton.setBackgroundResource(R.mipmap.right_button_disable) + + binding.searchResultView.text = "未检测到标识器" + binding.searchResultView.setTextColor(Color.parseColor("#8D1717")) + binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_red) + } else if (energy >= 4100) {//148° + binding.energyTipsView.text = "标识器信号极强,可能在正下方" + binding.energyTipsView.setTextColor(Color.parseColor("#428d00")) + binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_green) + } else {//[18°,148°] + binding.energyTipsView.text = "已靠近标识器,请继续移动位置" + binding.energyTipsView.setTextColor(Color.parseColor("#8C5700")) + binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_yellow) + } + } catch (e: NumberFormatException) { + e.printStackTrace() + } + } else if (hex.startsWith("53")) { + LoadingDialogHub.dismiss() + countDownTimer.cancel() + try { + val depthResponse = hex.take(10).hexToString() + val depth = depthResponse.drop(2).toInt() + AlertMessageDialog.Builder().setContext(context).setTitle("温馨提示") + .setMessage("标识器埋深:${depth}厘米").setPositiveButton("知道了") + .setOnDialogButtonClickListener(object : + AlertMessageDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + initTimer() + } + }).build().show() + } catch (e: NumberFormatException) { + e.printStackTrace() + } + } else { + val id = hex.take(20).hexToString() + if (id.isNumber()) { + markerId = id + + binding.depthButton.isEnabled = true + binding.depthButton.setTextColor(Color.WHITE) + binding.depthButton.setBackgroundResource(R.mipmap.left_button_enable) + binding.markerInfoButton.isEnabled = true + binding.markerInfoButton.setTextColor(Color.WHITE) + binding.markerInfoButton.setBackgroundResource(R.mipmap.right_button_enable) + + binding.searchResultView.text = "已检测到标识器" + binding.searchResultView.setTextColor(Color.parseColor("#428d00")) + binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_green) + + //自动上传标识器 +// taskBean = DataBaseManager.get.queryTaskLabelByIdAndState(markerId, "未开始") +// taskBean?.apply { +// /** +// * 此taskCode是 [com.casic.detector.model.TaskModel.MessageModel.TaskDetailInfosModel] 里面的主键,也就是这个标签在数据库里面的主键 +// * */ +// taskViewModel.uploadMarker(taskCode) +// } + } + } + } + + private fun initTimer() { + searchMarkerTimer = Timer() + + signalTask = object : TimerTask() { + override fun run() { + out.write('2'.code) + out.flush() + } + } + + energyTask = object : TimerTask() { + override fun run() { + out.write('6'.code) + out.flush() + } + } + + //错开信号和能量定时器 + searchMarkerTimer.schedule(signalTask, 0, 201) + searchMarkerTimer.schedule(energyTask, 0, 251) + } + + override fun dismiss() { + signalTask.cancel() + energyTask.cancel() + searchMarkerTimer.cancel() + //降低串口电位 + gpioManager.setGpioLow("18") + isDetectMarker = false + soundPool.autoPause() + super.dismiss() + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt b/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt index 6a00429..cbd6137 100644 --- a/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt @@ -13,18 +13,16 @@ import com.casic.electric.detector.R import com.casic.electric.detector.databinding.ActivityVersionControlBinding import com.casic.electric.detector.extensions.appendDownloadUrl -import com.casic.electric.detector.extensions.initLayoutImmersionBar +import com.casic.electric.detector.extensions.initImmersionBar import com.casic.electric.detector.utils.FileType -import com.casic.electric.detector.utils.LoadingDialogHub import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.vm.VersionViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.createDownloadFileDir -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.FileDownloadManager +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import java.io.File @@ -90,8 +88,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(true).init() - initLayoutImmersionBar(binding.rootView) + binding.rootView.initImmersionBar(this, true, R.color.white) binding.titleInclude.titleView.visibility = View.GONE } @@ -108,22 +105,26 @@ val downloadPath = url!!.appendDownloadUrl(FileType.APK) Log.d(kTag, "downloadApk => $downloadPath") //开始下载 - downloadPath.downloadFile(createDownloadFileDir().toString(), object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() - } + FileDownloadManager.Builder() + .setDownloadFileSource(downloadPath) + .setFileSuffix("apk") + .setFileSaveDirectory(createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadEnd(file: File) { + progressDialog.dismiss() + progressDialog.progress = 0 + //安装APK + installApk(file) + } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } + override fun onFailure(throwable: Throwable) { - override fun onDownloadEnd(file: File?) { - progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK - installApk(file) - } - }) + } + + override fun onProgressChanged(progress: Int) { + progressDialog.progress = progress + } + }).build().start() } private fun installApk(apkPackage: File?) { diff --git a/app/src/main/java/com/casic/electric/detector/vm/TaskViewModel.kt b/app/src/main/java/com/casic/electric/detector/vm/TaskViewModel.kt index 476a5f0..4b0bed6 100644 --- a/app/src/main/java/com/casic/electric/detector/vm/TaskViewModel.kt +++ b/app/src/main/java/com/casic/electric/detector/vm/TaskViewModel.kt @@ -2,125 +2,156 @@ import androidx.lifecycle.MutableLiveData import com.casic.electric.detector.base.BaseApplication -import com.casic.electric.detector.extensions.convertChinese -import com.casic.electric.detector.extensions.separateResponseState -import com.casic.electric.detector.extensions.toErrorMessage +import com.casic.electric.detector.extensions.getResponseMessage +import com.casic.electric.detector.extensions.getResponseState import com.casic.electric.detector.model.MarkerFileModel import com.casic.electric.detector.retrofit.RetrofitServiceManager import com.casic.electric.detector.utils.LabelDataClass +import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.SmallLabelDataClass import com.google.gson.Gson +import com.google.gson.JsonParser import com.google.gson.reflect.TypeToken +import com.pengxh.kt.lite.base.BaseViewModel import com.pengxh.kt.lite.extensions.launch import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.SaveKeyValues class TaskViewModel : BaseViewModel() { private val gson by lazy { Gson() } val markerFileResult = MutableLiveData() -// val taskResult = MutableLiveData() + + // val taskResult = MutableLiveData() + val freeTaskResult = MutableLiveData() + val uploadTaskMarkerResult = MutableLiveData() + + fun createFreeTask(patrollerId: String, description: String) = launch({ + val response = RetrofitServiceManager.createFreeTask(patrollerId, description) + if (response.getResponseState()) { + val element = JsonParser.parseString(response) + val jsonObject = element.asJsonObject + freeTaskResult.value = jsonObject.get("taskId").asInt.toString() + } else { + response.getResponseMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) + + fun uploadTaskMarker(taskId: String, models: ArrayList) = launch({ + val response = RetrofitServiceManager.uploadTaskMarker(taskId, models) + if (response.getResponseState()) { + val element = JsonParser.parseString(response) + val jsonObject = element.asJsonObject + uploadTaskMarkerResult.value = jsonObject.get("success").asString + } else { + response.getResponseMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) fun getMarkerFile(userId: String, companyId: String) = launch({ val response = RetrofitServiceManager.getMarkerFile(userId, companyId) - if (response.separateResponseState()) { + if (response.getResponseState()) { markerFileResult.value = gson.fromJson( response, object : TypeToken() {}.type ) } else { - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { - it.convertChinese().show(BaseApplication.get()) + it.printStackTrace() }) -// fun getTask(userName: String) = launch({ -// val response = RetrofitServiceManager.getTask(userName) -// if (response.separateResponseState()) { + fun getTask(userName: String) = launch({ + val response = RetrofitServiceManager.getTask(userName) + if (response.getResponseState()) { // taskResult.value = gson.fromJson( // response, object : TypeToken() {}.type // ) -// } else { -// response.toErrorMessage().show(BaseApplication.get()) -// } -// }, { -// it.convertChinese().show(BaseApplication.get()) -// }) + } else { + response.getResponseMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) fun installLabel(labelData: LabelDataClass) = launch({ loadState.value = LoadState.Loading val response = RetrofitServiceManager.installLabel(labelData) - if (response.separateResponseState()) { + if (response.getResponseState()) { loadState.value = LoadState.Success } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { + it.printStackTrace() loadState.value = LoadState.Fail - it.convertChinese().show(BaseApplication.get()) }) fun installSmallLabel(labelData: SmallLabelDataClass) = launch({ loadState.value = LoadState.Loading val response = RetrofitServiceManager.installSmallLabel(labelData) - if (response.separateResponseState()) { + if (response.getResponseState()) { loadState.value = LoadState.Success } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { + it.printStackTrace() loadState.value = LoadState.Fail - it.convertChinese().show(BaseApplication.get()) }) -// fun uploadTask(userId: String, taskId: String?, state: String) = launch({ -// loadState.value = LoadState.Loading -// val response = RetrofitServiceManager.uploadTask(userId, taskId, state) -// if (response.separateResponseState()) { -// loadState.value = LoadState.Success -// if (state == "2") { -// "工单${taskId}已提交!".show(BaseApplication.get()) -// //删除本地数据库 + fun uploadTask(userId: String, taskId: String?, state: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.uploadTask(userId, taskId, state) + if (response.getResponseState()) { + loadState.value = LoadState.Success + if (state == "2") { + "工单${taskId}已提交!".show(BaseApplication.get()) + //删除本地数据库 // DataBaseManager.get.deleteTaskById(taskId) -// SaveKeyValues.putValue(LocaleConstant.TASK_ID, "") -// } -// } else { -// loadState.value = LoadState.Fail -// response.toErrorMessage().show(BaseApplication.get()) -// } -// }, { -// loadState.value = LoadState.Fail -// it.convertChinese().show(BaseApplication.get()) -// }) + SaveKeyValues.putValue(LocaleConstant.TASK_ID, "") + } + } else { + loadState.value = LoadState.Fail + response.getResponseMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + loadState.value = LoadState.Fail + }) fun uploadEvent(taskId: String, event: String, realPaths: ArrayList) = launch({ loadState.value = LoadState.Loading val response = RetrofitServiceManager.uploadEvent(taskId, event, realPaths) - if (response.separateResponseState()) { + if (response.getResponseState()) { loadState.value = LoadState.Success } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { + it.printStackTrace() loadState.value = LoadState.Fail - it.convertChinese().show(BaseApplication.get()) }) - fun uploadMarker(userName: String, taskDetailId: String) = launch({ + fun uploadMarker(taskDetailId: String) = launch({ loadState.value = LoadState.Loading - val response = RetrofitServiceManager.uploadMarker(userName, taskDetailId) - if (response.separateResponseState()) { + val response = RetrofitServiceManager.uploadMarker(taskDetailId) + if (response.getResponseState()) { loadState.value = LoadState.Success } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { + it.printStackTrace() loadState.value = LoadState.Fail - it.convertChinese().show(BaseApplication.get()) }) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/vm/UserViewModel.kt b/app/src/main/java/com/casic/electric/detector/vm/UserViewModel.kt index e4a7b4e..ee6099b 100644 --- a/app/src/main/java/com/casic/electric/detector/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/electric/detector/vm/UserViewModel.kt @@ -2,17 +2,17 @@ import androidx.lifecycle.MutableLiveData import com.casic.electric.detector.base.BaseApplication -import com.casic.electric.detector.extensions.separateResponseState -import com.casic.electric.detector.extensions.toErrorMessage +import com.casic.electric.detector.extensions.getResponseMessage +import com.casic.electric.detector.extensions.getResponseState import com.casic.electric.detector.model.LoginResultModel import com.casic.electric.detector.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +import com.pengxh.kt.lite.base.BaseViewModel import com.pengxh.kt.lite.extensions.isNetworkConnected import com.pengxh.kt.lite.extensions.launch import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState /** * 用户相关 VM @@ -25,14 +25,14 @@ fun login(account: String, password: String) = launch({ loadState.value = LoadState.Loading val response = RetrofitServiceManager.login(account, password) - if (response.separateResponseState()) { + if (response.getResponseState()) { loadState.value = LoadState.Success loginResult.value = gson.fromJson( response, object : TypeToken() {}.type ) } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { loadState.value = LoadState.Fail diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt b/app/src/main/java/com/casic/electric/detector/extensions/Context.kt deleted file mode 100644 index fcf36a7..0000000 --- a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.casic.electric.detector.extensions - -import android.content.Context -import android.view.ViewGroup -import com.pengxh.kt.lite.extensions.getStatusBarHeight - -/** - * 设置沉浸式状态栏,兼容Android 11+ - * */ -fun Context.initLayoutImmersionBar(rootView: ViewGroup) { - rootView.setPadding(0, this.getStatusBarHeight(), 0, 0) - rootView.requestLayout() -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt index 6e08b27..e98408a 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt @@ -13,12 +13,4 @@ paint.color = color canvas.drawArc(rectF, 0f, 360f, true, paint) return bitmap -} - -fun Int.appendZero(): String { - return if (this < 10) { - "0$this" - } else { - this.toString() - } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/String.kt b/app/src/main/java/com/casic/electric/detector/extensions/String.kt index a0db0eb..838d3ad 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/String.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/String.kt @@ -3,14 +3,11 @@ import android.content.Context import android.widget.TextView import com.casic.electric.detector.callback.OnImageCompressListener -import com.casic.electric.detector.model.ErrorMessageModel import com.casic.electric.detector.utils.FileType import com.casic.electric.detector.utils.LocaleConstant -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken +import com.google.gson.JsonParser import com.pengxh.kt.lite.extensions.createCompressImageDir import com.pengxh.kt.lite.utils.SaveKeyValues -import org.json.JSONObject import top.zibin.luban.Luban import top.zibin.luban.OnCompressListener import java.io.File @@ -18,18 +15,22 @@ /** * String扩展方法 */ -fun String.separateResponseState(): Boolean { +fun String.getResponseState(): Boolean { if (this.isBlank()) { return false } - return JSONObject(this).getBoolean("success") + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("success").asBoolean } -fun String.toErrorMessage(): String { - val errorModel = Gson().fromJson( - this, object : TypeToken() {}.type - ) - return errorModel.message.toString() +fun String.getResponseMessage(): String { + if (this.isBlank()) { + return "" + } + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("message").asString } /** @@ -131,4 +132,9 @@ } else { "6" } +} + +fun String.isNumber(): Boolean { + val regex = Regex("[-+]?\\d+(\\.\\d+)?") + return this.matches(regex) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt new file mode 100644 index 0000000..8b78a3c --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt @@ -0,0 +1,31 @@ +package com.casic.electric.detector.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import androidx.fragment.app.Fragment +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} + +fun ViewGroup.initImmersionBar(fragment: Fragment, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(fragment) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(fragment.requireContext())) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = fragment.requireContext().getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt new file mode 100644 index 0000000..84c9cd9 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt @@ -0,0 +1,3 @@ +package com.casic.electric.detector.model + +data class CalculateResult(val angle: Int, val direction: String, val distance: Int) diff --git a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java b/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java deleted file mode 100644 index 1574393..0000000 --- a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.casic.electric.detector.model; - -public class ErrorMessageModel { - private int code; - private String data; - private String exceptionClazz; - private String message; - private boolean isSuccess; - - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public String getExceptionClazz() { - return exceptionClazz; - } - - public void setExceptionClazz(String exceptionClazz) { - this.exceptionClazz = exceptionClazz; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public boolean isSuccess() { - return isSuccess; - } - - public void setSuccess(boolean success) { - isSuccess = success; - } -} diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt index 950fb91..f590226 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt @@ -90,10 +90,25 @@ /** * 上传工单中标识器信息 + * info中的主键 */ @GET("/ems/rs/task/update-task-mark") suspend fun uploadMarker( - @Query("userName") userId: String, - @Query("taskDetailId") taskId: String, + @Query("taskDetailId") taskId: String ): String + + /** + * 新建自由巡检任务 + * */ + @GET("ems/rs/task/addAppTask") + suspend fun createFreeTask( + @Query("patrollerId") patrollerId: String, + @Query("description") description: String + ): String + + /** + * 上传自由巡检过程中发现的标识器 + * */ + @POST("ems/event/uploadAppMarker.do") + suspend fun uploadTaskMarker(@Body requestBody: RequestBody): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt index 6834fc5..7836b28 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt @@ -1,5 +1,6 @@ package com.casic.electric.detector.retrofit +import com.casic.electric.detector.extensions.reformat import com.casic.electric.detector.utils.LabelDataClass import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.SmallLabelDataClass @@ -15,43 +16,32 @@ object RetrofitServiceManager { + private fun createApi(): RetrofitService { + val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String + val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String + val httpConfig = "http://${serverIp}:${serverPort}" + return RetrofitFactory.createRetrofit(httpConfig) + } + /** * 登录 */ suspend fun login(account: String, password: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.login(account, password) + return createApi().login(account, password) } /** * 更新版本 * */ suspend fun getApplicationVersion(): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getApplicationVersion() + return createApi().getApplicationVersion() } /** * 获取标识器信息文件 */ suspend fun getMarkerFile(userId: String, companyId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getMarkerFile(userId, companyId) + return createApi().getMarkerFile(userId, companyId) } /** @@ -64,39 +54,21 @@ "application/json;charset=UTF-8".toMediaType() ) - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getLabelPicture(requestBody) + return createApi().getLabelPicture(requestBody) } /** * 获取巡检工单 */ suspend fun getTask(userName: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getTask(userName) + return createApi().getTask(userName) } /** * 提交工单 */ suspend fun uploadTask(userId: String, taskId: String?, state: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadTask(userId, taskId.toString(), state) + return createApi().uploadTask(userId, taskId.toString(), state) } /** @@ -164,27 +136,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installLabel(res, multiParts[0], multiParts[1], null) + createApi().installLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installLabel(res, multiParts[0], null, null) + createApi().installLabel(res, multiParts[0], null, null) } else -> { - api.installLabel(res, null, null, null) + createApi().installLabel(res, null, null, null) } } } @@ -230,27 +196,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], null) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installSmallLabel(res, multiParts[0], null, null) + createApi().installSmallLabel(res, multiParts[0], null, null) } else -> { - api.installSmallLabel(res, null, null, null) + createApi().installSmallLabel(res, null, null, null) } } } @@ -279,27 +239,23 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2]) + createApi().uploadEvent( + taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2] + ) } 2 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) } 1 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) } else -> { - api.uploadEvent(taskIdMap, eventMap, null, null, null) + createApi().uploadEvent(taskIdMap, eventMap, null, null, null) } } } @@ -307,13 +263,27 @@ /** * 上传工单中标识器信息 */ - suspend fun uploadMarker(userName: String, taskDetailId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadMarker(userName, taskDetailId) + suspend fun uploadMarker(taskDetailId: String): String { + return createApi().uploadMarker(taskDetailId) + } + + /** + * 上传工单中标识器信息 + */ + suspend fun createFreeTask(patrollerId: String, description: String): String { + return createApi().createFreeTask(patrollerId, description) + } + + /** + * 上传自由巡检过程中发现的标识器 + */ + suspend fun uploadTaskMarker(taskId: String, models: ArrayList): String { + val param = JsonObject() + param.addProperty("taskId", taskId) + param.addProperty("ids", models.reformat()) + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return createApi().uploadTaskMarker(requestBody) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java index 4aba809..45d5a2f 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java +++ b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java @@ -1,8 +1,10 @@ package com.casic.electric.detector.utils; -public class GpioManager { +import android.util.Log; +public class GpioManager { + private static final String TAG = "GpioManager"; private static final int MT6761 = 0; private int selected; private final MT6761Gpio mt6761; @@ -38,6 +40,7 @@ * 璁剧疆GPIO杈撳嚭楂� * *********************************************************************/ public void setGpioHigh(String gpio) { + Log.d(TAG, "setGpioHigh: 调高电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioHigh(); @@ -48,6 +51,7 @@ * 璁剧疆GPIO杈撳嚭浣� * *********************************************************************/ public void setGpioLow(String gpio) { + Log.d(TAG, "setGpioLow: 调低电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioLow(); diff --git a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt deleted file mode 100644 index c589c4b..0000000 --- a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.electric.detector.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt index 4de12f2..9356f9a 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt @@ -13,7 +13,7 @@ ) const val PERMISSIONS_CODE = 999 - const val RADIUS_SIZE = 100f //相距多少米才聚合,单位:米 + const val RADIUS_SIZE = 100 //相距多少米才聚合,单位:米 const val AUTO_SAVE = "AUTO_SAVE" const val USER_ACCOUNT = "USER_ACCOUNT" @@ -28,10 +28,21 @@ const val APP_AUTHORITY = "com.casic.electric.detector.fileprovider" val POPUP_TITLES = arrayOf("更新数据", "下载工单", "关于软件", "事件上报", "标识器补全") - var CONDITION_ARRAY = arrayOf("种类", "编号", "名称", "所属区域", "所属道路", "运检单位", "责任人", "建设时间", "标识器ID") + var CONDITION_ARRAY = arrayOf( + "种类", + "编号", + "名称", + "所属区域", + "所属道路", + "运检单位", + "责任人", + "建设时间", + "标识器ID" + ) var CONTENT_ARRAY = arrayOf("电缆井", "电缆通道", "配电房", "开关站", "台区", "杆塔") var OBJECT_MODE_ARRAY = arrayOf("直线井", "转弯井", "丁字井", "十字井", "其他") - var WELL_COVER_MATERIAL_ARRAY_1 = arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") + var WELL_COVER_MATERIAL_ARRAY_1 = + arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") var WELL_COVER_MATERIAL_ARRAY_2 = arrayOf("水泥杆", "钢管杆", "铁塔", "其他") var CABINET_TYPE_ARRAY = arrayOf("无", "SM6", "SAFE", "RM6", "XGN15", "固体柜") var PIPE_MATERIAL_ARRAY = arrayOf("无", "PVC管", "波纹管", "镀锌钢管") @@ -42,7 +53,16 @@ var CROSS_PIPE_STATE_ARRAY = booleanArrayOf(false, false, false, false, false, false, false) var POINT_TYPE_ARRAY = arrayOf("管线", "管线附属物", "管线特征管点", "交叉穿越点") - var SPINNER_ARRAY = arrayOf("标识器ID", "所属区域", "所属线路", "所属道路", "权属单位", "安装部门", "安装时间", "备注") + var SPINNER_ARRAY = arrayOf( + "标识器ID", + "所属区域", + "所属线路", + "所属道路", + "权属单位", + "安装部门", + "安装时间", + "备注" + ) var DOWN_PIPE_TYPE_ARRAY = arrayOf("热力", "燃气", "供水", "电力", "通信") var BURY_METHOD_ARRAY = arrayOf("直埋", "圆管", "管块", "管沟", "架空") var COLOR_ARRAY = arrayOf("蓝色", "橙色", "红色", "黑色", "紫色", "黄色", "绿色") diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt index 4f0f2c7..61e55f6 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt @@ -14,14 +14,16 @@ import com.casic.electric.detector.callback.IAddressListener import com.casic.electric.detector.callback.ILocationListener -object LocationHub { - private const val kTag = "LocationHub" +class LocationHub constructor(context: Context) { - fun getCurrentLocation(context: Context, listener: ILocationListener) { - val locationClient = AMapLocationClient(context) + private val kTag = "LocationHub" + private val locationClient by lazy { AMapLocationClient(context) } + private val codeSearch by lazy { GeocodeSearch(context) } + + fun getCurrentLocation(isOnceLocation: Boolean, listener: ILocationListener) { val locationOption = AMapLocationClientOption() locationOption.locationMode = AMapLocationClientOption.AMapLocationMode.Hight_Accuracy - locationOption.isOnceLocation = true + locationOption.isOnceLocation = isOnceLocation locationClient.setLocationOption(locationOption) locationClient.setLocationListener { if (it.errorCode == 0) { @@ -36,9 +38,8 @@ locationClient.startLocation() } - fun antiCodingLocation(context: Context, location: Location, listener: IAddressListener) { + fun antiCodingLocation(location: Location, listener: IAddressListener) { try { - val codeSearch = GeocodeSearch(context) // 第一个参数表示一个LatLonPoint,第二参数表示范围多少米,第三个参数表示是火系坐标系还是GPS原生坐标系 val query = RegeocodeQuery( LatLonPoint(location.latitude, location.longitude), 10f, GeocodeSearch.AMAP @@ -55,4 +56,8 @@ e.printStackTrace() } } + + fun stopLocation() { + locationClient.stopLocation() + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt b/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt index aa1bdeb..e3d3289 100644 --- a/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt @@ -1,7 +1,6 @@ package com.casic.electric.detector.view import android.content.Context -import android.graphics.Color import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -12,10 +11,10 @@ import com.bumptech.glide.Glide import com.casic.electric.detector.R import com.casic.electric.detector.databinding.ActivityBigImageBinding +import com.casic.electric.detector.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class BigImageActivity : KotlinBaseActivity() { @@ -24,20 +23,12 @@ } override fun setupTopBarLayout() { - ImmerseStatusBarUtil.setColor(this, Color.BLACK) + binding.rootView.initImmersionBar(this, false, R.color.black) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - val index: Int = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return @@ -62,6 +53,14 @@ }) } + override fun observeRequestState() { + + } + + override fun initEvent() { + + } + inner class BigImageAdapter( private val context: Context, private val data: ArrayList ) : PagerAdapter() { diff --git a/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt b/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt index d3a89ca..6510104 100644 --- a/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt @@ -29,15 +29,15 @@ import com.casic.electric.detector.extensions.* import com.casic.electric.detector.utils.* import com.casic.electric.detector.vm.TaskViewModel -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia import com.luck.picture.lib.interfaces.OnResultCallbackListener import com.pengxh.kt.lite.extensions.* +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -53,7 +53,8 @@ private val context: Context = this@InstallLabelActivity private val gpioManager by lazy { GpioManager() } private val calendar by lazy { Calendar.getInstance() } - private val realPaths: ArrayList = ArrayList() //真实图片路径 + private val locationHub by lazy { LocationHub(this) } + private val realPaths = ArrayList() //真实图片路径 private var soundResId = 0 private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var soundPool: SoundPool @@ -67,12 +68,6 @@ override fun setupTopBarLayout() { binding.titleInclude.titleView.text = "安装新标识器" binding.titleInclude.titleView.setTextColor(R.color.themeColor.convertColor(this)) - - ImmersionBar.with(this) - .statusBarDarkFont(true) - .statusBarColor(R.color.mainBackground) - .init() - initLayoutImmersionBar(binding.rootView) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -126,7 +121,7 @@ binding.markerAttrInclude.remarkView3.setText("remarkView3".getDefaultValue()) //初始化图片九宫格 - imageAdapter = EditableImageAdapter(this, 3, 3f) + imageAdapter = EditableImageAdapter(this, 3, 3) binding.cameraInclude.addImageRecyclerView.adapter = imageAdapter taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] @@ -332,7 +327,7 @@ binding.markerAttrInclude.installTimeView.text = System.currentTimeMillis().timestampToCompleteDate() - LocationHub.getCurrentLocation(this, object : ILocationListener { + locationHub.getCurrentLocation(true, object : ILocationListener { override fun onAMapLocationGet(location: AMapLocation?) { if (location != null) { binding.markerAttrInclude.lngView.text = location.longitude.toString() @@ -518,8 +513,8 @@ weakReferenceHandler.postDelayed({ try { // 发送读标识器或搜索信号 - outputStream?.write("2".toByteArray()) - outputStream?.flush() + out.write("2".toByteArray()) + out.flush() } catch (e: IOException) { e.printStackTrace() } @@ -527,7 +522,7 @@ } } - override fun onDataReceived(buffer: ByteArray?, size: Int) { + override fun onDataReceived(buffer: ByteArray) { Log.d(kTag, "onDataReceived => " + buffer.contentToString()) if (buffer != null) { val message = weakReferenceHandler.obtainMessage() diff --git a/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt b/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt index 5bc2ac8..286bf4a 100644 --- a/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt @@ -24,7 +24,6 @@ import com.casic.electric.detector.extensions.* import com.casic.electric.detector.utils.* import com.casic.electric.detector.vm.TaskViewModel -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -33,9 +32,10 @@ import com.pengxh.kt.lite.extensions.isNetworkConnected import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -65,12 +65,6 @@ override fun setupTopBarLayout() { binding.titleInclude.titleView.text = "安装新电子标签" binding.titleInclude.titleView.setTextColor(R.color.themeColor.convertColor(this)) - - ImmersionBar.with(this) - .statusBarDarkFont(true) - .statusBarColor(R.color.mainBackground) - .init() - initLayoutImmersionBar(binding.rootView) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -103,7 +97,7 @@ binding.objectAttrInclude.objectRemarkView3.setText("objectRemarkView3".getDefaultValue()) //初始化图片九宫格 - imageAdapter = EditableImageAdapter(this, 3, 3f) + imageAdapter = EditableImageAdapter(this, 3, 3) binding.cameraInclude.addImageRecyclerView.adapter = imageAdapter taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] @@ -308,8 +302,8 @@ weakReferenceHandler.postDelayed({ try { // 发送读标识器或搜索信号 - outputStream?.write("2".toByteArray()) - outputStream?.flush() + out.write("2".toByteArray()) + out.flush() } catch (e: IOException) { e.printStackTrace() } @@ -317,7 +311,7 @@ } } - override fun onDataReceived(buffer: ByteArray?, size: Int) { + override fun onDataReceived(buffer: ByteArray) { if (buffer != null) { val message = weakReferenceHandler.obtainMessage() message.what = 2023081702 diff --git a/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt b/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt index 44d56ef..9c98b5f 100644 --- a/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt @@ -1,36 +1,29 @@ package com.casic.electric.detector.view import android.os.Bundle -import android.util.Log import androidx.lifecycle.ViewModelProvider import com.amap.api.navi.NaviSetting import com.casic.electric.detector.databinding.ActivityLoginBinding -import com.casic.electric.detector.extensions.initLayoutImmersionBar -import com.casic.electric.detector.utils.GpioManager -import com.casic.electric.detector.utils.LoadingDialogHub import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.vm.UserViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.getScreenHeight -import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog class LoginActivity : KotlinBaseActivity() { private val kTag = "LoginActivity" private lateinit var userViewModel: UserViewModel - private val gpioManager by lazy { GpioManager() } override fun initViewBinding(): ActivityLoginBinding { return ActivityLoginBinding.inflate(layoutInflater) } override fun initOnCreate(savedInstanceState: Bundle?) { - gpioManager.setGpioLow("18") //先把导航隐私政策声明,后面导航会用到 NaviSetting.updatePrivacyShow(this, true, true) NaviSetting.updatePrivacyAgree(this, true) @@ -60,11 +53,8 @@ val serversIp = binding.serversIpView.text.toString() val serversPort = binding.serversPortView.text.toString() if (account.isBlank() || password.isBlank() || serversIp.isBlank() || serversPort.isBlank()) { - AlertMessageDialog.Builder() - .setContext(this) - .setTitle("账号登录") - .setMessage("信息不能为空哦!") - .setPositiveButton("知道了") + AlertMessageDialog.Builder().setContext(this).setTitle("账号登录") + .setMessage("信息不能为空哦!").setPositiveButton("知道了") .setOnDialogButtonClickListener(object : AlertMessageDialog.OnDialogButtonClickListener { override fun onConfirmClick() { @@ -102,9 +92,6 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(true).init() - initLayoutImmersionBar(binding.rootView) - - Log.d(kTag, "setupTopBarLayout => [${getScreenWidth()}, ${getScreenHeight()}]") } override fun onResume() { diff --git a/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt b/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt index 36a8d55..a0a4aac 100644 --- a/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt @@ -1,15 +1,21 @@ package com.casic.electric.detector.view +import android.annotation.SuppressLint import android.app.AlertDialog +import android.app.Dialog import android.content.Context -import android.content.Intent import android.graphics.Color import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable +import android.media.AudioAttributes +import android.media.SoundPool import android.os.Bundle -import android.os.PowerManager -import android.provider.Settings +import android.os.CountDownTimer +import android.util.Log import android.view.KeyEvent +import android.view.View +import android.view.animation.Animation +import android.view.animation.RotateAnimation import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import com.amap.api.location.AMapLocation @@ -21,6 +27,8 @@ import com.amap.api.maps.model.LatLngBounds import com.amap.api.maps.model.MyLocationStyle import com.casic.electric.detector.R +import com.casic.electric.detector.adapter.EditableImageAdapter +import com.casic.electric.detector.base.SerialPortActivity import com.casic.electric.detector.bean.LabelBean import com.casic.electric.detector.bean.SmallLabelBean import com.casic.electric.detector.bean.TaskBean @@ -29,83 +37,109 @@ import com.casic.electric.detector.cluster.ClusterOverlay import com.casic.electric.detector.cluster.RegionItem import com.casic.electric.detector.databinding.ActivityMainBinding +import com.casic.electric.detector.databinding.DialogInstallMarkerBinding +import com.casic.electric.detector.databinding.DialogInstallSmallMarkerBinding +import com.casic.electric.detector.databinding.DialogSearchMarkerBinding import com.casic.electric.detector.extensions.appendExcelDownloadUrl import com.casic.electric.detector.extensions.drawCircle -import com.casic.electric.detector.extensions.initLayoutImmersionBar +import com.casic.electric.detector.extensions.hexToString +import com.casic.electric.detector.extensions.initImmersionBar +import com.casic.electric.detector.extensions.isNumber +import com.casic.electric.detector.extensions.toHex import com.casic.electric.detector.utils.DataBaseManager import com.casic.electric.detector.utils.ExcelHub -import com.casic.electric.detector.utils.LoadingDialogHub +import com.casic.electric.detector.utils.GpioManager import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.LocationHub import com.casic.electric.detector.utils.RouteOnMap import com.casic.electric.detector.vm.TaskViewModel import com.casic.electric.detector.widgets.QueryMarkerDialog import com.casic.electric.detector.widgets.SamplePopupWindow -import com.gyf.immersionbar.ImmersionBar -import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.callback.OnDownloadListener +import com.google.gson.Gson +import com.pengxh.kt.lite.extensions.binding import com.pengxh.kt.lite.extensions.createDownloadFileDir -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.dp2px +import com.pengxh.kt.lite.extensions.initDialogLayoutParams import com.pengxh.kt.lite.extensions.isNetworkConnected import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.toJson +import com.pengxh.kt.lite.utils.FileDownloadManager +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog +import com.pengxh.kt.lite.widget.dialog.AlertInputDialog +import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File +import java.text.DecimalFormat +import java.util.Calendar +import java.util.Timer +import java.util.TimerTask -class MainActivity : KotlinBaseActivity() { +@SuppressLint("all") +class MainActivity : SerialPortActivity() { private val kTag = "MainActivity" - private val context: Context = this@MainActivity + private val context = this@MainActivity + private val gpioManager by lazy { GpioManager() } private val samplePopupWindow by lazy { SamplePopupWindow(this) } + private val gson by lazy { Gson() } + private val locationHub by lazy { LocationHub(this) } + private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } + private val backDrawables by lazy { HashMap() } + private val installMarkerDialog by lazy { InstallMarkerDialog(this) } + private val installSmallMarkerDialog by lazy { InstallSmallMarkerDialog(this) } + private val searchDialog by lazy { SearchMarkerDialog(this) } private var clickTime: Long = 0 - private lateinit var wakeLock: PowerManager.WakeLock - private lateinit var aMap: AMap - private lateinit var taskViewModel: TaskViewModel - private lateinit var taskBean: TaskBean - private var latitude: Double = 0.0 - private var longitude: Double = 0.0 private var labels = ArrayList() private var smallLabels = ArrayList() private var clusterOverlay: ClusterOverlay? = null - private val backDrawables = HashMap() - private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } + private var latitude: Double = 0.0 + private var longitude: Double = 0.0 + private var isFreeTask = false + private var ids = ArrayList() + private var signalTask: TimerTask? = null + private var searchMarkerTimer: Timer? = null + private lateinit var aMap: AMap + private lateinit var taskBean: TaskBean + private lateinit var taskId: String + + /***inner class 需要用到*****start*/ + private val taskViewModel by lazy { ViewModelProvider(this)[TaskViewModel::class.java] } + 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 var soundResourceId = 0 + private var slowSoundResourceId = 0 + private var fastSoundResourceId = 0 + + /***inner class 需要用到*****end*/ override fun initViewBinding(): ActivityMainBinding { return ActivityMainBinding.inflate(layoutInflater) } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).statusBarColor(R.color.themeColor).init() - initLayoutImmersionBar(binding.rootView) - } - - override fun observeRequestState() { - + binding.rootView.initImmersionBar(this, false, R.color.themeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { - val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager - wakeLock = powerManager.run { - newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this@MainActivity.localClassName).apply { - acquire(60 * 60 * 1000L) - } - } + soundResourceId = soundPool.load(this, R.raw.ring3, 1) + slowSoundResourceId = soundPool.load(this, R.raw.ring4, 1) + fastSoundResourceId = soundPool.load(this, R.raw.ring2, 1) + //地图初始化 initMapConfig(savedInstanceState) samplePopupWindow.setPopupMenuItem(LocaleConstant.POPUP_TITLES) samplePopupWindow.setBackgroundDrawable(null) - taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] + //task网络请求监听 taskViewModel.markerFileResult.observe(this) { if (it.success == "true") { //清空之前的数据 @@ -122,11 +156,13 @@ val smallLabelDownloadUrl = urlArray[1].appendExcelDownloadUrl() //下载标识器 - labelDownloadUrl.downloadFile( - createDownloadFileDir().toString(), object : OnDownloadListener { - override fun onDownloadEnd(file: File?) { + FileDownloadManager.Builder().setDownloadFileSource(labelDownloadUrl) + .setFileSuffix("xls").setFileSaveDirectory(createDownloadFileDir()) + .setOnFileDownloadListener(object : + FileDownloadManager.OnFileDownloadListener { + override fun onDownloadEnd(file: File) { lifecycleScope.launch { - labels = ExcelHub.readLabel(file?.absolutePath) + labels = ExcelHub.readLabel(file.absolutePath) withContext(Dispatchers.IO) { labels.forEach { label -> DataBaseManager.get.insertLabel(label) @@ -137,21 +173,23 @@ } } - override fun onDownloadStart(totalBytes: Long) { + override fun onFailure(throwable: Throwable) { } - override fun onProgressChanged(currentBytes: Long) { + override fun onProgressChanged(progress: Int) { } - }) + }).build().start() //下载附属标识器 - smallLabelDownloadUrl.downloadFile( - createDownloadFileDir().toString(), object : OnDownloadListener { - override fun onDownloadEnd(file: File?) { + FileDownloadManager.Builder().setDownloadFileSource(smallLabelDownloadUrl) + .setFileSuffix("xls").setFileSaveDirectory(createDownloadFileDir()) + .setOnFileDownloadListener(object : + FileDownloadManager.OnFileDownloadListener { + override fun onDownloadEnd(file: File) { lifecycleScope.launch { - smallLabels = ExcelHub.readSmallLabel(file?.absolutePath) + smallLabels = ExcelHub.readSmallLabel(file.absolutePath) withContext(Dispatchers.IO) { smallLabels.forEach { label -> DataBaseManager.get.insertSmallLabel(label) @@ -160,14 +198,14 @@ } } - override fun onDownloadStart(totalBytes: Long) { + override fun onFailure(throwable: Throwable) { } - override fun onProgressChanged(currentBytes: Long) { + override fun onProgressChanged(progress: Int) { } - }) + }).build().start() } } } @@ -175,11 +213,8 @@ // if (it.success == "true") { // //清空之前的数据 // DataBaseManager.get.clearTasks() -// AlertMessageDialog.Builder() -// .setContext(this) -// .setTitle("温馨提示") -// .setMessage("您有${it.message.size}个新任务!") -// .setPositiveButton("知道了") +// AlertMessageDialog.Builder().setContext(this).setTitle("温馨提示") +// .setMessage("您有${it.message.size}个新任务!").setPositiveButton("知道了") // .setOnDialogButtonClickListener(object : // AlertMessageDialog.OnDialogButtonClickListener { // override fun onConfirmClick() { @@ -188,19 +223,24 @@ // }).build().show() // } // } + taskViewModel.freeTaskResult.observe(this) { taskId = it } + taskViewModel.uploadTaskMarkerResult.observe(this) { + "自由巡检任务已完成".show(this) + ids.clear() + } } override fun initEvent() { binding.rightImageView.setOnClickListener { - CoroutineScope(Dispatchers.Main).launch { + lifecycleScope.launch(Dispatchers.Main) { val labels = withContext(Dispatchers.IO) { DataBaseManager.get.queryLabelById("0") } if (labels.isNotEmpty()) { samplePopupWindow.setShowPosition(4) } - val x = binding.rightImageView.width - samplePopupWindow.width - 1f.dp2px(context) - samplePopupWindow.showAsDropDown(binding.rightImageView, x, 1f.dp2px(context)) + val x = binding.rightImageView.width - samplePopupWindow.width - 1.dp2px(context) + samplePopupWindow.showAsDropDown(binding.rightImageView, x, 1.dp2px(context)) } } @@ -219,35 +259,33 @@ //安装。上传,然后存入本地库 binding.installButton.setOnClickListener { - AlertControlDialog.Builder() - .setContext(context) - .setTitle("提示") - .setMessage("请选择安装对象") - .setPositiveButton("标识器") - .setNegativeButton("电子标签") - .setOnDialogButtonClickListener(object : + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("请选择安装对象").setPositiveButton("标识器") + .setNegativeButton("电子标签").setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { //标识器 - navigatePageTo() + /** + * 改为Dialog方式,避免频繁打开/关闭串口 + * */ + installMarkerDialog.show() } override fun onCancelClick() { //电子标签 - navigatePageTo() + /** + * 改为Dialog方式,避免频繁打开/关闭串口 + * */ + installSmallMarkerDialog.show() } }).build().show() } //查看 binding.viewButton.setOnClickListener { - QueryMarkerDialog.Builder() - .setContext(this) - .setTitle("查看标识器") - .setConditionArray(LocaleConstant.CONDITION_ARRAY) - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : + QueryMarkerDialog.Builder().setContext(this).setTitle("查看标识器") + .setConditionArray(LocaleConstant.CONDITION_ARRAY).setNegativeButton("取消") + .setPositiveButton("确定").setOnDialogButtonClickListener(object : QueryMarkerDialog.OnDialogButtonClickListener { override fun onConfirmClick( selectedCondition: String, vararg contentValue: String @@ -310,30 +348,25 @@ // arrayList.add("任务${index + 1}:${taskBean.taskId},${taskBean.desc}") // } // -// BottomActionSheet.Builder() -// .setContext(this) -// .setItemTextColor(Color.BLUE) +// BottomActionSheet.Builder().setContext(this).setItemTextColor(Color.BLUE) // .setActionItemTitle(arrayList) // .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { // override fun onActionItemClick(position: Int) { // val taskBean = task[position] // SaveKeyValues.putValue(LocaleConstant.TASK_ID, taskBean.taskId) -// AlertControlDialog.Builder() -// .setContext(context) -// .setTitle("提示") -// .setMessage("请选择操作方式") -// .setPositiveButton("执行工单") +// AlertControlDialog.Builder().setContext(context).setTitle("提示") +// .setMessage("请选择操作方式").setPositiveButton("执行工单") // .setNegativeButton("提交工单") // .setOnDialogButtonClickListener(object : // AlertControlDialog.OnDialogButtonClickListener { // override fun onConfirmClick() { // detectRedrawGraphic(taskBean.taskId) +// +// val latLng = LatLng( +// taskBean.lat.toDouble(), taskBean.lng.toDouble() +// ) // aMap.moveCamera( -// CameraUpdateFactory.newLatLngZoom( -// LatLng( -// taskBean.lat.toDouble(), taskBean.lng.toDouble() -// ), 15f -// ) +// CameraUpdateFactory.newLatLngZoom(latLng, 16f) // ) // uploadTask(taskBean.taskId, "1") // } @@ -345,15 +378,12 @@ // } // }).build().show() // } else { -// AlertMessageDialog.Builder() -// .setContext(this) -// .setTitle("温馨提示") -// .setMessage("现有任务已完成,请点击右上角菜单按钮下载新工单!") -// .setPositiveButton("知道了") -// .setOnDialogButtonClickListener(object : +// AlertMessageDialog.Builder().setContext(this).setTitle("温馨提示") +// .setMessage("现有任务已完成,请点击右上角菜单下载新工单或者开始自由巡检") +// .setPositiveButton("知道了").setOnDialogButtonClickListener(object : // AlertMessageDialog.OnDialogButtonClickListener { // override fun onConfirmClick() { -// +// startFreeTask() // } // }).build().show() // } @@ -361,7 +391,118 @@ //探测 binding.detectionButton.setOnClickListener { -// navigatePageTo() + /** + * 改为Dialog方式,避免频繁打开/关闭串口 + * */ + searchDialog.show() + } + + //自由巡检 + binding.stopFreeTaskButton.setOnLongClickListener { + AlertMessageDialog.Builder().setContext(this).setTitle("温馨提示") + .setMessage("是否确定结束此次自由巡检任务?").setPositiveButton("是") + .setOnDialogButtonClickListener(object : + AlertMessageDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + isFreeTask = false + soundPool.autoPause() + + //降低串口电位 + gpioManager.setGpioLow("18") + + taskViewModel.uploadTaskMarker(taskId, ids) + binding.stopFreeTaskButton.visibility = View.GONE + } + }).build().show() + true + } + } + + private fun startFreeTask() { + AlertInputDialog.Builder().setContext(this).setTitle("新建自由巡检任务") + .setHintMessage("请输入自由巡检任务简要描述").setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : AlertInputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String + taskViewModel.createFreeTask(userId, value) + + //调高串口电位 + gpioManager.setGpioHigh("18") + + soundPool.play(soundResourceId, 1f, 1f, 0, -1, 1f) + isFreeTask = true + //自由巡检 + signalTask = object : TimerTask() { + override fun run() { + out.write('2'.code) + out.flush() + } + } + searchMarkerTimer = Timer() + searchMarkerTimer?.apply { + schedule(signalTask, 0, 100) + } + + binding.stopFreeTaskButton.visibility = View.VISIBLE + } + + override fun onCancelClick() {} + }).build().show() + } + + override fun onDataReceived(buffer: ByteArray) { + val hex = buffer.toHex() + Log.d(kTag, "$kTag => $hex") + if (searchDialog.isDetectMarker) { + searchDialog.bindingValue(hex) +// } else if (installMarkerDialog.isReadMarker) { +// val markerId = hex.take(20).hexToString() +// if (markerId.isNumber()) { +// installMarkerDialog.bindingValue(markerId) +// } +// } else if (installSmallMarkerDialog.isReadMarker) { +// val markerId = hex.take(20).hexToString() +// if (markerId.isNumber()) { +// installSmallMarkerDialog.bindingValue(markerId) +// } + } else if (isFreeTask) { + val markerId = hex.take(20).hexToString() + if (markerId.isNumber()) { + "标识器${markerId}已探测".show(this) + ids.add(markerId) + } + } + } + + override fun observeRequestState() { + taskViewModel.loadState.observe(this) { + when (it) { + LoadState.Loading -> { + if (installMarkerDialog.isInstallMarker || installSmallMarkerDialog.isInstallMarker) { + LoadingDialogHub.show(this, "标识器安装中,请稍后...") + } else if (searchDialog.isDetectMarker) { + searchDialog.taskBean?.apply { + "标识器${this.markerId}已探测!".show(context) +// DataBaseManager.get.updateTaskLabel(this) + } + } else { + LoadingDialogHub.show(this, "提交工单中,请稍后") + } + } + + else -> { + if (installMarkerDialog.isInstallMarker) { + installMarkerDialog.dismiss() + installMarkerDialog.isInstallMarker = false + } else if (installSmallMarkerDialog.isInstallMarker) { + installSmallMarkerDialog.dismiss() + installSmallMarkerDialog.isInstallMarker = false + } + LoadingDialogHub.dismiss() + } + } + detectRedrawGraphic(taskBean.taskId) } } @@ -375,6 +516,7 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜 //显示定位小蓝点 val locationStyle = MyLocationStyle() locationStyle.interval(2000) @@ -387,7 +529,7 @@ longitude = it.longitude latitude = it.latitude //经纬度逆编码 - LocationHub.antiCodingLocation(context, it) { address -> + locationHub.antiCodingLocation(it) { address -> binding.currentLocationView.text = address } } @@ -417,7 +559,7 @@ } private fun moveToCurrentLocation() { - LocationHub.getCurrentLocation(this, object : ILocationListener { + locationHub.getCurrentLocation(true, object : ILocationListener { override fun onAMapLocationGet(location: AMapLocation?) { if (location != null) { aMap.moveCamera( @@ -432,46 +574,35 @@ }) } - //更新数据 - private fun updateLabels() { - AlertControlDialog.Builder() - .setContext(this) - .setTitle("提示") - .setMessage("是否更新数据?") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onConfirmClick() { - if (isNetworkConnected()) { - val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") - val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") - - LoadingDialogHub.show(this@MainActivity, "获取标识器信息中,请稍后") - //TODO 设计如此,都传companyId - taskViewModel.getMarkerFile(companyId.toString(), companyId.toString()) - } else { - NoNetworkDialog.Builder() - .setContext(context) - .setOnDialogButtonClickListener(object : - NoNetworkDialog.OnDialogButtonClickListener { - override fun onButtonClick() { - val intent = Intent(Settings.ACTION_SETTINGS) - startActivity(intent) - } - }).build().show() - } - } - - override fun onCancelClick() { - - } - }).build().show() - } +// private fun saveTaskInformation(it: TaskModel) { +// val userName = SaveKeyValues.getValue(LocaleConstant.USER_NAME, "") as String +// if (it.message.size > 0) { +// it.message.forEach { messageModel -> +// val count = DataBaseManager.get.countTaskById(messageModel.id.toString()) +// if (count == 0) { +// messageModel.taskDetailInfos.forEach { info -> +// DataBaseManager.get.insertTaskInformation( +// userName, +// messageModel.description, +// info.taskId.toString(), +// info.id.toString(), +// info.markerId.toString(), +// info.markerIdReal.toString(), +// info.longitude.toString(), +// info.latitude.toString(), +// messageModel.status +// ) +// } +// } +// } +// "工单下载成功!".show(context) +// } +// } private fun showLabelsOnMap() { clusterOverlay?.onDestroy() val clusterItems = ArrayList() + labels.forEach { val latLng = LatLng(it.latitude.toDouble(), it.longitude.toDouble(), false) val regionItem = RegionItem(latLng, it.markerId.toString()) @@ -480,7 +611,7 @@ clusterOverlay = ClusterOverlay(context, aMap, clusterItems, regionRadius) clusterOverlay?.setClusterRender { clusterNum -> - val radius = 80f.dp2px(context) + val radius = 80.dp2px(context) if (clusterNum == 0) { var bitmapDrawable = backDrawables[0] if (bitmapDrawable == null) { @@ -546,9 +677,7 @@ val latLngBounds = builder.build() aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 0)) - BottomActionSheet.Builder() - .setContext(this) - .setItemTextColor(Color.BLUE) + BottomActionSheet.Builder().setContext(this).setItemTextColor(Color.BLUE) .setActionItemTitle(listOf("标识器信息", "附属电子标签信息", "到这里去")) .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { override fun onActionItemClick(position: Int) { @@ -578,12 +707,7 @@ showElectricMarkers(electricMarkers) } - 2 -> { - RouteOnMap.startNavigation( - context, item.tag, - LatLng(item.position.latitude, item.position.longitude) - ) - } + 2 -> RouteOnMap.startNavigation(context, item.tag, latLng) } } }).build().show() @@ -591,14 +715,74 @@ } private fun showElectricMarkers(markers: ArrayList) { - AlertDialog.Builder(context) - .setIcon(R.mipmap.ic_launcher) - .setTitle("电子标签列表") + AlertDialog.Builder(context).setIcon(R.mipmap.ic_launcher).setTitle("电子标签列表") .setSingleChoiceItems(markers.toTypedArray(), -1) { _, which -> navigatePageTo(markers[which]) }.show() } + private fun detectRedrawGraphic(taskId: String) { +// val tasks = DataBaseManager.get.queryTaskById(taskId) +// if (tasks.isNotEmpty()) { +// tasks.forEach { +// val latLng = LatLng(it.lat.toDouble(), it.lng.toDouble()) +// val otMarkerOptions = MarkerOptions() +// otMarkerOptions.position(latLng) +// otMarkerOptions.visible(true) // 设置可见 +// if (it.state == "未开始") { +// otMarkerOptions.icon( +// BitmapDescriptorFactory.fromBitmap( +// BitmapFactory.decodeResource(resources, R.mipmap.label_red1) +// ) +// ).period(99).title("工单标识器").snippet(it.markerId) +// } else { +// otMarkerOptions.icon( +// BitmapDescriptorFactory.fromBitmap( +// BitmapFactory.decodeResource(resources, R.mipmap.label_blue1) +// ) +// ).period(99).title("工单标识器").snippet(it.markerId) +// } +// aMap.addMarker(otMarkerOptions) +// } +// } + showLabelsOnMap() + } + + private fun uploadTask(taskId: String?, state: String) { + if (isNetworkConnected()) { + val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String + taskViewModel.uploadTask(userId, taskId, state) + } else { + "网络连接已断开,请检查".show(this) + } + } + + //更新数据 + private fun updateLabels() { + AlertControlDialog.Builder().setContext(this).setTitle("提示").setMessage("是否更新数据?") + .setNegativeButton("取消").setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + if (isNetworkConnected()) { + val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") + + LoadingDialogHub.show(this@MainActivity, "获取标识器信息中,请稍后") + /** + * 后台设计如此,都传companyId + * */ + taskViewModel.getMarkerFile(companyId.toString(), companyId.toString()) + } else { + "网络连接已断开,请检查".show(context) + } + } + + override fun onCancelClick() { + + } + }).build().show() + } + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { return if (keyCode == KeyEvent.KEYCODE_BACK) { if (System.currentTimeMillis() - clickTime > 2000) { @@ -643,8 +827,270 @@ } override fun onDestroy() { - wakeLock.release() super.onDestroy() binding.mapView.onDestroy() + signalTask?.cancel() + searchMarkerTimer?.cancel() + soundPool.release() + locationHub.stopLocation() + //降低串口电位 + gpioManager.setGpioLow("18") + } + + /**安装标识器对话框******************************************************************************/ + inner class InstallMarkerDialog(context: Context) : Dialog(context) { + + private val binding: DialogInstallMarkerBinding by binding() + private val calendar by lazy { Calendar.getInstance() } + private val realPaths = ArrayList() //真实图片路径 + private lateinit var imageAdapter: EditableImageAdapter + + var isReadMarker = false + var isInstallMarker = false + } + + /**安装小标签对话框******************************************************************************/ + inner class InstallSmallMarkerDialog(context: Context) : Dialog(context) { + + private val binding: DialogInstallSmallMarkerBinding by binding() + private val calendar by lazy { Calendar.getInstance() } + private val realPaths = ArrayList() //真实图片路径 + private lateinit var imageAdapter: EditableImageAdapter + + var isReadMarker = false + var isInstallMarker = false + } + + /**探测标识器对话框******************************************************************************/ + inner class SearchMarkerDialog(context: Context) : Dialog(context) { + + private val binding: DialogSearchMarkerBinding by binding() + private val decimal by lazy { DecimalFormat("0.0") } + private val degreeCache by lazy { HashMap() } + private var isPlaying = false + private var markerId = "" + private lateinit var searchMarkerTimer: Timer + private lateinit var signalTask: TimerTask + private lateinit var energyTask: TimerTask + private lateinit var countDownTimer: CountDownTimer + + var isDetectMarker = false + var taskBean: TaskBean? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.initDialogLayoutParams(1f) + binding.depthButton.setOnClickListener { + signalTask.cancel() + energyTask.cancel() + searchMarkerTimer.cancel() + + out.write('3'.code) +// val result = DataBaseManager.get.queryLabelById(markerId) +// if (result.isNotEmpty()) { +// val tag = when (result.first().identifierType) { +// "EM30" -> '7' +// "EM50" -> '8' +// "EM14" -> '9' +// else -> '1' +// } +// if (tag == '1') { +// "此标识器无法读取埋深!".show(context) +// } else { +// // 发送读取标识器埋设深度指令 +// LoadingDialogHub.show(this@MainActivity, "正在测距,请稍后...") +// out.write(tag.code) +// out.flush() +// countDownTimer = object : CountDownTimer(15 * 1000, 1000) { +// override fun onTick(millisUntilFinished: Long) { +// +// } +// +// override fun onFinish() { +// LoadingDialogHub.dismiss() +// "探测此标识器深度超时,请重试".show(context) +// initTimer() +// } +// } +// countDownTimer.start() +// } +// } else { +// "标识器未安装,安装成功后才可读取埋深!".show(context) +// } + } + + binding.markerInfoButton.setOnClickListener { + //查库 + val result = DataBaseManager.get.queryLabelById(markerId) + if (result.isNotEmpty()) { +// context.navigatePageTo(result.first().toJson()) + } else { +// context.navigatePageTo(markerId) + } + } + } + + override fun onStart() { + super.onStart() + //调高串口电位 + gpioManager.setGpioHigh("18") + + initTimer() + + isDetectMarker = true + + //角度 + degreeCache["lastDegree"] = 0f + } + + fun bindingValue(hex: String) { + if (hex.startsWith("4E")) { + try { + //4E转为String为N,代表能量值 + //用能量值转动表盘 + val energyResponse = hex.take(10).hexToString() + val energy = energyResponse.substring(1).toInt() + if (energy >= 4000) { + isPlaying = if (!isPlaying) { + soundPool.play(fastSoundResourceId, 1f, 1f, 0, 0, 1f) + true + } else { + soundPool.pause(fastSoundResourceId) + false + } + } else { + isPlaying = if (!isPlaying) { + soundPool.play(slowSoundResourceId, 1f, 1f, 0, 0, 1f) + true + } else { + soundPool.pause(slowSoundResourceId) + false + } + } + + binding.resultTextView.text = "信号能量值:${energyResponse}" + + //转换为转动的角度 + val degree = (energy.toFloat() / (50 * 100)) * 180 + binding.energyValueView.text = decimal.format(degree) + + degreeCache["lastDegree"]?.apply { + val animation = RotateAnimation( + this, degree, + Animation.RELATIVE_TO_SELF, 0.5f, + Animation.RELATIVE_TO_SELF, 0.5f + ) + animation.duration = 0 + animation.fillAfter = true + binding.needleView.startAnimation(animation) + } + + //保存旋转后的角度 + degreeCache["lastDegree"] = degree + + if (energy <= 700) {//18° + binding.energyTipsView.text = "标识器信号较弱,可能距离较远" + binding.energyTipsView.setTextColor(Color.parseColor("#8D1717")) + binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_red) + + binding.depthButton.isEnabled = false + binding.depthButton.setTextColor(Color.parseColor("#CCCCCC")) + binding.depthButton.setBackgroundResource(R.mipmap.left_button_disable) + binding.markerInfoButton.isEnabled = false + binding.markerInfoButton.setTextColor(Color.parseColor("#CCCCCC")) + binding.markerInfoButton.setBackgroundResource(R.mipmap.right_button_disable) + + binding.searchResultView.text = "未检测到标识器" + binding.searchResultView.setTextColor(Color.parseColor("#8D1717")) + binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_red) + } else if (energy >= 4100) {//148° + binding.energyTipsView.text = "标识器信号极强,可能在正下方" + binding.energyTipsView.setTextColor(Color.parseColor("#428d00")) + binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_green) + } else {//[18°,148°] + binding.energyTipsView.text = "已靠近标识器,请继续移动位置" + binding.energyTipsView.setTextColor(Color.parseColor("#8C5700")) + binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_yellow) + } + } catch (e: NumberFormatException) { + e.printStackTrace() + } + } else if (hex.startsWith("53")) { + LoadingDialogHub.dismiss() + countDownTimer.cancel() + try { + val depthResponse = hex.take(10).hexToString() + val depth = depthResponse.drop(2).toInt() + AlertMessageDialog.Builder().setContext(context).setTitle("温馨提示") + .setMessage("标识器埋深:${depth}厘米").setPositiveButton("知道了") + .setOnDialogButtonClickListener(object : + AlertMessageDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + initTimer() + } + }).build().show() + } catch (e: NumberFormatException) { + e.printStackTrace() + } + } else { + val id = hex.take(20).hexToString() + if (id.isNumber()) { + markerId = id + + binding.depthButton.isEnabled = true + binding.depthButton.setTextColor(Color.WHITE) + binding.depthButton.setBackgroundResource(R.mipmap.left_button_enable) + binding.markerInfoButton.isEnabled = true + binding.markerInfoButton.setTextColor(Color.WHITE) + binding.markerInfoButton.setBackgroundResource(R.mipmap.right_button_enable) + + binding.searchResultView.text = "已检测到标识器" + binding.searchResultView.setTextColor(Color.parseColor("#428d00")) + binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_green) + + //自动上传标识器 +// taskBean = DataBaseManager.get.queryTaskLabelByIdAndState(markerId, "未开始") +// taskBean?.apply { +// /** +// * 此taskCode是 [com.casic.detector.model.TaskModel.MessageModel.TaskDetailInfosModel] 里面的主键,也就是这个标签在数据库里面的主键 +// * */ +// taskViewModel.uploadMarker(taskCode) +// } + } + } + } + + private fun initTimer() { + searchMarkerTimer = Timer() + + signalTask = object : TimerTask() { + override fun run() { + out.write('2'.code) + out.flush() + } + } + + energyTask = object : TimerTask() { + override fun run() { + out.write('6'.code) + out.flush() + } + } + + //错开信号和能量定时器 + searchMarkerTimer.schedule(signalTask, 0, 201) + searchMarkerTimer.schedule(energyTask, 0, 251) + } + + override fun dismiss() { + signalTask.cancel() + energyTask.cancel() + searchMarkerTimer.cancel() + //降低串口电位 + gpioManager.setGpioLow("18") + isDetectMarker = false + soundPool.autoPause() + super.dismiss() + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt b/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt index 6a00429..cbd6137 100644 --- a/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt @@ -13,18 +13,16 @@ import com.casic.electric.detector.R import com.casic.electric.detector.databinding.ActivityVersionControlBinding import com.casic.electric.detector.extensions.appendDownloadUrl -import com.casic.electric.detector.extensions.initLayoutImmersionBar +import com.casic.electric.detector.extensions.initImmersionBar import com.casic.electric.detector.utils.FileType -import com.casic.electric.detector.utils.LoadingDialogHub import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.vm.VersionViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.createDownloadFileDir -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.FileDownloadManager +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import java.io.File @@ -90,8 +88,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(true).init() - initLayoutImmersionBar(binding.rootView) + binding.rootView.initImmersionBar(this, true, R.color.white) binding.titleInclude.titleView.visibility = View.GONE } @@ -108,22 +105,26 @@ val downloadPath = url!!.appendDownloadUrl(FileType.APK) Log.d(kTag, "downloadApk => $downloadPath") //开始下载 - downloadPath.downloadFile(createDownloadFileDir().toString(), object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() - } + FileDownloadManager.Builder() + .setDownloadFileSource(downloadPath) + .setFileSuffix("apk") + .setFileSaveDirectory(createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadEnd(file: File) { + progressDialog.dismiss() + progressDialog.progress = 0 + //安装APK + installApk(file) + } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } + override fun onFailure(throwable: Throwable) { - override fun onDownloadEnd(file: File?) { - progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK - installApk(file) - } - }) + } + + override fun onProgressChanged(progress: Int) { + progressDialog.progress = progress + } + }).build().start() } private fun installApk(apkPackage: File?) { diff --git a/app/src/main/java/com/casic/electric/detector/vm/TaskViewModel.kt b/app/src/main/java/com/casic/electric/detector/vm/TaskViewModel.kt index 476a5f0..4b0bed6 100644 --- a/app/src/main/java/com/casic/electric/detector/vm/TaskViewModel.kt +++ b/app/src/main/java/com/casic/electric/detector/vm/TaskViewModel.kt @@ -2,125 +2,156 @@ import androidx.lifecycle.MutableLiveData import com.casic.electric.detector.base.BaseApplication -import com.casic.electric.detector.extensions.convertChinese -import com.casic.electric.detector.extensions.separateResponseState -import com.casic.electric.detector.extensions.toErrorMessage +import com.casic.electric.detector.extensions.getResponseMessage +import com.casic.electric.detector.extensions.getResponseState import com.casic.electric.detector.model.MarkerFileModel import com.casic.electric.detector.retrofit.RetrofitServiceManager import com.casic.electric.detector.utils.LabelDataClass +import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.SmallLabelDataClass import com.google.gson.Gson +import com.google.gson.JsonParser import com.google.gson.reflect.TypeToken +import com.pengxh.kt.lite.base.BaseViewModel import com.pengxh.kt.lite.extensions.launch import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.SaveKeyValues class TaskViewModel : BaseViewModel() { private val gson by lazy { Gson() } val markerFileResult = MutableLiveData() -// val taskResult = MutableLiveData() + + // val taskResult = MutableLiveData() + val freeTaskResult = MutableLiveData() + val uploadTaskMarkerResult = MutableLiveData() + + fun createFreeTask(patrollerId: String, description: String) = launch({ + val response = RetrofitServiceManager.createFreeTask(patrollerId, description) + if (response.getResponseState()) { + val element = JsonParser.parseString(response) + val jsonObject = element.asJsonObject + freeTaskResult.value = jsonObject.get("taskId").asInt.toString() + } else { + response.getResponseMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) + + fun uploadTaskMarker(taskId: String, models: ArrayList) = launch({ + val response = RetrofitServiceManager.uploadTaskMarker(taskId, models) + if (response.getResponseState()) { + val element = JsonParser.parseString(response) + val jsonObject = element.asJsonObject + uploadTaskMarkerResult.value = jsonObject.get("success").asString + } else { + response.getResponseMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) fun getMarkerFile(userId: String, companyId: String) = launch({ val response = RetrofitServiceManager.getMarkerFile(userId, companyId) - if (response.separateResponseState()) { + if (response.getResponseState()) { markerFileResult.value = gson.fromJson( response, object : TypeToken() {}.type ) } else { - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { - it.convertChinese().show(BaseApplication.get()) + it.printStackTrace() }) -// fun getTask(userName: String) = launch({ -// val response = RetrofitServiceManager.getTask(userName) -// if (response.separateResponseState()) { + fun getTask(userName: String) = launch({ + val response = RetrofitServiceManager.getTask(userName) + if (response.getResponseState()) { // taskResult.value = gson.fromJson( // response, object : TypeToken() {}.type // ) -// } else { -// response.toErrorMessage().show(BaseApplication.get()) -// } -// }, { -// it.convertChinese().show(BaseApplication.get()) -// }) + } else { + response.getResponseMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) fun installLabel(labelData: LabelDataClass) = launch({ loadState.value = LoadState.Loading val response = RetrofitServiceManager.installLabel(labelData) - if (response.separateResponseState()) { + if (response.getResponseState()) { loadState.value = LoadState.Success } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { + it.printStackTrace() loadState.value = LoadState.Fail - it.convertChinese().show(BaseApplication.get()) }) fun installSmallLabel(labelData: SmallLabelDataClass) = launch({ loadState.value = LoadState.Loading val response = RetrofitServiceManager.installSmallLabel(labelData) - if (response.separateResponseState()) { + if (response.getResponseState()) { loadState.value = LoadState.Success } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { + it.printStackTrace() loadState.value = LoadState.Fail - it.convertChinese().show(BaseApplication.get()) }) -// fun uploadTask(userId: String, taskId: String?, state: String) = launch({ -// loadState.value = LoadState.Loading -// val response = RetrofitServiceManager.uploadTask(userId, taskId, state) -// if (response.separateResponseState()) { -// loadState.value = LoadState.Success -// if (state == "2") { -// "工单${taskId}已提交!".show(BaseApplication.get()) -// //删除本地数据库 + fun uploadTask(userId: String, taskId: String?, state: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.uploadTask(userId, taskId, state) + if (response.getResponseState()) { + loadState.value = LoadState.Success + if (state == "2") { + "工单${taskId}已提交!".show(BaseApplication.get()) + //删除本地数据库 // DataBaseManager.get.deleteTaskById(taskId) -// SaveKeyValues.putValue(LocaleConstant.TASK_ID, "") -// } -// } else { -// loadState.value = LoadState.Fail -// response.toErrorMessage().show(BaseApplication.get()) -// } -// }, { -// loadState.value = LoadState.Fail -// it.convertChinese().show(BaseApplication.get()) -// }) + SaveKeyValues.putValue(LocaleConstant.TASK_ID, "") + } + } else { + loadState.value = LoadState.Fail + response.getResponseMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + loadState.value = LoadState.Fail + }) fun uploadEvent(taskId: String, event: String, realPaths: ArrayList) = launch({ loadState.value = LoadState.Loading val response = RetrofitServiceManager.uploadEvent(taskId, event, realPaths) - if (response.separateResponseState()) { + if (response.getResponseState()) { loadState.value = LoadState.Success } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { + it.printStackTrace() loadState.value = LoadState.Fail - it.convertChinese().show(BaseApplication.get()) }) - fun uploadMarker(userName: String, taskDetailId: String) = launch({ + fun uploadMarker(taskDetailId: String) = launch({ loadState.value = LoadState.Loading - val response = RetrofitServiceManager.uploadMarker(userName, taskDetailId) - if (response.separateResponseState()) { + val response = RetrofitServiceManager.uploadMarker(taskDetailId) + if (response.getResponseState()) { loadState.value = LoadState.Success } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { + it.printStackTrace() loadState.value = LoadState.Fail - it.convertChinese().show(BaseApplication.get()) }) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/vm/UserViewModel.kt b/app/src/main/java/com/casic/electric/detector/vm/UserViewModel.kt index e4a7b4e..ee6099b 100644 --- a/app/src/main/java/com/casic/electric/detector/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/electric/detector/vm/UserViewModel.kt @@ -2,17 +2,17 @@ import androidx.lifecycle.MutableLiveData import com.casic.electric.detector.base.BaseApplication -import com.casic.electric.detector.extensions.separateResponseState -import com.casic.electric.detector.extensions.toErrorMessage +import com.casic.electric.detector.extensions.getResponseMessage +import com.casic.electric.detector.extensions.getResponseState import com.casic.electric.detector.model.LoginResultModel import com.casic.electric.detector.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +import com.pengxh.kt.lite.base.BaseViewModel import com.pengxh.kt.lite.extensions.isNetworkConnected import com.pengxh.kt.lite.extensions.launch import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState /** * 用户相关 VM @@ -25,14 +25,14 @@ fun login(account: String, password: String) = launch({ loadState.value = LoadState.Loading val response = RetrofitServiceManager.login(account, password) - if (response.separateResponseState()) { + if (response.getResponseState()) { loadState.value = LoadState.Success loginResult.value = gson.fromJson( response, object : TypeToken() {}.type ) } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { loadState.value = LoadState.Fail diff --git a/app/src/main/java/com/casic/electric/detector/vm/VersionViewModel.kt b/app/src/main/java/com/casic/electric/detector/vm/VersionViewModel.kt index 6caf065..b488b5b 100644 --- a/app/src/main/java/com/casic/electric/detector/vm/VersionViewModel.kt +++ b/app/src/main/java/com/casic/electric/detector/vm/VersionViewModel.kt @@ -7,10 +7,10 @@ import com.casic.electric.detector.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +import com.pengxh.kt.lite.base.BaseViewModel import com.pengxh.kt.lite.extensions.launch import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class VersionViewModel : BaseViewModel() { private val gson by lazy { Gson() } diff --git a/app/build.gradle b/app/build.gradle index 093bae7..623fc18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ applicationId "com.casic.electric.detector" minSdkVersion 22 targetSdkVersion 33 - versionCode 1 - versionName "1.0.0.0" + versionCode 5020 + versionName "5.0.2" ndk { moduleName "serial_port" @@ -69,7 +69,7 @@ implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.5.3' //Google官方授权框架 implementation 'pub.devrel:easypermissions:3.0.0' //腾讯Android UI框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7fc0db..14e9b51 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -90,7 +90,7 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt b/app/src/main/java/com/casic/electric/detector/extensions/Context.kt deleted file mode 100644 index fcf36a7..0000000 --- a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.casic.electric.detector.extensions - -import android.content.Context -import android.view.ViewGroup -import com.pengxh.kt.lite.extensions.getStatusBarHeight - -/** - * 设置沉浸式状态栏,兼容Android 11+ - * */ -fun Context.initLayoutImmersionBar(rootView: ViewGroup) { - rootView.setPadding(0, this.getStatusBarHeight(), 0, 0) - rootView.requestLayout() -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt index 6e08b27..e98408a 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt @@ -13,12 +13,4 @@ paint.color = color canvas.drawArc(rectF, 0f, 360f, true, paint) return bitmap -} - -fun Int.appendZero(): String { - return if (this < 10) { - "0$this" - } else { - this.toString() - } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/String.kt b/app/src/main/java/com/casic/electric/detector/extensions/String.kt index a0db0eb..838d3ad 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/String.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/String.kt @@ -3,14 +3,11 @@ import android.content.Context import android.widget.TextView import com.casic.electric.detector.callback.OnImageCompressListener -import com.casic.electric.detector.model.ErrorMessageModel import com.casic.electric.detector.utils.FileType import com.casic.electric.detector.utils.LocaleConstant -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken +import com.google.gson.JsonParser import com.pengxh.kt.lite.extensions.createCompressImageDir import com.pengxh.kt.lite.utils.SaveKeyValues -import org.json.JSONObject import top.zibin.luban.Luban import top.zibin.luban.OnCompressListener import java.io.File @@ -18,18 +15,22 @@ /** * String扩展方法 */ -fun String.separateResponseState(): Boolean { +fun String.getResponseState(): Boolean { if (this.isBlank()) { return false } - return JSONObject(this).getBoolean("success") + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("success").asBoolean } -fun String.toErrorMessage(): String { - val errorModel = Gson().fromJson( - this, object : TypeToken() {}.type - ) - return errorModel.message.toString() +fun String.getResponseMessage(): String { + if (this.isBlank()) { + return "" + } + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("message").asString } /** @@ -131,4 +132,9 @@ } else { "6" } +} + +fun String.isNumber(): Boolean { + val regex = Regex("[-+]?\\d+(\\.\\d+)?") + return this.matches(regex) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt new file mode 100644 index 0000000..8b78a3c --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt @@ -0,0 +1,31 @@ +package com.casic.electric.detector.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import androidx.fragment.app.Fragment +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} + +fun ViewGroup.initImmersionBar(fragment: Fragment, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(fragment) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(fragment.requireContext())) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = fragment.requireContext().getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt new file mode 100644 index 0000000..84c9cd9 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt @@ -0,0 +1,3 @@ +package com.casic.electric.detector.model + +data class CalculateResult(val angle: Int, val direction: String, val distance: Int) diff --git a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java b/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java deleted file mode 100644 index 1574393..0000000 --- a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.casic.electric.detector.model; - -public class ErrorMessageModel { - private int code; - private String data; - private String exceptionClazz; - private String message; - private boolean isSuccess; - - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public String getExceptionClazz() { - return exceptionClazz; - } - - public void setExceptionClazz(String exceptionClazz) { - this.exceptionClazz = exceptionClazz; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public boolean isSuccess() { - return isSuccess; - } - - public void setSuccess(boolean success) { - isSuccess = success; - } -} diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt index 950fb91..f590226 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt @@ -90,10 +90,25 @@ /** * 上传工单中标识器信息 + * info中的主键 */ @GET("/ems/rs/task/update-task-mark") suspend fun uploadMarker( - @Query("userName") userId: String, - @Query("taskDetailId") taskId: String, + @Query("taskDetailId") taskId: String ): String + + /** + * 新建自由巡检任务 + * */ + @GET("ems/rs/task/addAppTask") + suspend fun createFreeTask( + @Query("patrollerId") patrollerId: String, + @Query("description") description: String + ): String + + /** + * 上传自由巡检过程中发现的标识器 + * */ + @POST("ems/event/uploadAppMarker.do") + suspend fun uploadTaskMarker(@Body requestBody: RequestBody): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt index 6834fc5..7836b28 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt @@ -1,5 +1,6 @@ package com.casic.electric.detector.retrofit +import com.casic.electric.detector.extensions.reformat import com.casic.electric.detector.utils.LabelDataClass import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.SmallLabelDataClass @@ -15,43 +16,32 @@ object RetrofitServiceManager { + private fun createApi(): RetrofitService { + val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String + val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String + val httpConfig = "http://${serverIp}:${serverPort}" + return RetrofitFactory.createRetrofit(httpConfig) + } + /** * 登录 */ suspend fun login(account: String, password: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.login(account, password) + return createApi().login(account, password) } /** * 更新版本 * */ suspend fun getApplicationVersion(): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getApplicationVersion() + return createApi().getApplicationVersion() } /** * 获取标识器信息文件 */ suspend fun getMarkerFile(userId: String, companyId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getMarkerFile(userId, companyId) + return createApi().getMarkerFile(userId, companyId) } /** @@ -64,39 +54,21 @@ "application/json;charset=UTF-8".toMediaType() ) - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getLabelPicture(requestBody) + return createApi().getLabelPicture(requestBody) } /** * 获取巡检工单 */ suspend fun getTask(userName: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getTask(userName) + return createApi().getTask(userName) } /** * 提交工单 */ suspend fun uploadTask(userId: String, taskId: String?, state: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadTask(userId, taskId.toString(), state) + return createApi().uploadTask(userId, taskId.toString(), state) } /** @@ -164,27 +136,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installLabel(res, multiParts[0], multiParts[1], null) + createApi().installLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installLabel(res, multiParts[0], null, null) + createApi().installLabel(res, multiParts[0], null, null) } else -> { - api.installLabel(res, null, null, null) + createApi().installLabel(res, null, null, null) } } } @@ -230,27 +196,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], null) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installSmallLabel(res, multiParts[0], null, null) + createApi().installSmallLabel(res, multiParts[0], null, null) } else -> { - api.installSmallLabel(res, null, null, null) + createApi().installSmallLabel(res, null, null, null) } } } @@ -279,27 +239,23 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2]) + createApi().uploadEvent( + taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2] + ) } 2 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) } 1 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) } else -> { - api.uploadEvent(taskIdMap, eventMap, null, null, null) + createApi().uploadEvent(taskIdMap, eventMap, null, null, null) } } } @@ -307,13 +263,27 @@ /** * 上传工单中标识器信息 */ - suspend fun uploadMarker(userName: String, taskDetailId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadMarker(userName, taskDetailId) + suspend fun uploadMarker(taskDetailId: String): String { + return createApi().uploadMarker(taskDetailId) + } + + /** + * 上传工单中标识器信息 + */ + suspend fun createFreeTask(patrollerId: String, description: String): String { + return createApi().createFreeTask(patrollerId, description) + } + + /** + * 上传自由巡检过程中发现的标识器 + */ + suspend fun uploadTaskMarker(taskId: String, models: ArrayList): String { + val param = JsonObject() + param.addProperty("taskId", taskId) + param.addProperty("ids", models.reformat()) + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return createApi().uploadTaskMarker(requestBody) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java index 4aba809..45d5a2f 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java +++ b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java @@ -1,8 +1,10 @@ package com.casic.electric.detector.utils; -public class GpioManager { +import android.util.Log; +public class GpioManager { + private static final String TAG = "GpioManager"; private static final int MT6761 = 0; private int selected; private final MT6761Gpio mt6761; @@ -38,6 +40,7 @@ * 璁剧疆GPIO杈撳嚭楂� * *********************************************************************/ public void setGpioHigh(String gpio) { + Log.d(TAG, "setGpioHigh: 调高电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioHigh(); @@ -48,6 +51,7 @@ * 璁剧疆GPIO杈撳嚭浣� * *********************************************************************/ public void setGpioLow(String gpio) { + Log.d(TAG, "setGpioLow: 调低电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioLow(); diff --git a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt deleted file mode 100644 index c589c4b..0000000 --- a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.electric.detector.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt index 4de12f2..9356f9a 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt @@ -13,7 +13,7 @@ ) const val PERMISSIONS_CODE = 999 - const val RADIUS_SIZE = 100f //相距多少米才聚合,单位:米 + const val RADIUS_SIZE = 100 //相距多少米才聚合,单位:米 const val AUTO_SAVE = "AUTO_SAVE" const val USER_ACCOUNT = "USER_ACCOUNT" @@ -28,10 +28,21 @@ const val APP_AUTHORITY = "com.casic.electric.detector.fileprovider" val POPUP_TITLES = arrayOf("更新数据", "下载工单", "关于软件", "事件上报", "标识器补全") - var CONDITION_ARRAY = arrayOf("种类", "编号", "名称", "所属区域", "所属道路", "运检单位", "责任人", "建设时间", "标识器ID") + var CONDITION_ARRAY = arrayOf( + "种类", + "编号", + "名称", + "所属区域", + "所属道路", + "运检单位", + "责任人", + "建设时间", + "标识器ID" + ) var CONTENT_ARRAY = arrayOf("电缆井", "电缆通道", "配电房", "开关站", "台区", "杆塔") var OBJECT_MODE_ARRAY = arrayOf("直线井", "转弯井", "丁字井", "十字井", "其他") - var WELL_COVER_MATERIAL_ARRAY_1 = arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") + var WELL_COVER_MATERIAL_ARRAY_1 = + arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") var WELL_COVER_MATERIAL_ARRAY_2 = arrayOf("水泥杆", "钢管杆", "铁塔", "其他") var CABINET_TYPE_ARRAY = arrayOf("无", "SM6", "SAFE", "RM6", "XGN15", "固体柜") var PIPE_MATERIAL_ARRAY = arrayOf("无", "PVC管", "波纹管", "镀锌钢管") @@ -42,7 +53,16 @@ var CROSS_PIPE_STATE_ARRAY = booleanArrayOf(false, false, false, false, false, false, false) var POINT_TYPE_ARRAY = arrayOf("管线", "管线附属物", "管线特征管点", "交叉穿越点") - var SPINNER_ARRAY = arrayOf("标识器ID", "所属区域", "所属线路", "所属道路", "权属单位", "安装部门", "安装时间", "备注") + var SPINNER_ARRAY = arrayOf( + "标识器ID", + "所属区域", + "所属线路", + "所属道路", + "权属单位", + "安装部门", + "安装时间", + "备注" + ) var DOWN_PIPE_TYPE_ARRAY = arrayOf("热力", "燃气", "供水", "电力", "通信") var BURY_METHOD_ARRAY = arrayOf("直埋", "圆管", "管块", "管沟", "架空") var COLOR_ARRAY = arrayOf("蓝色", "橙色", "红色", "黑色", "紫色", "黄色", "绿色") diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt index 4f0f2c7..61e55f6 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt @@ -14,14 +14,16 @@ import com.casic.electric.detector.callback.IAddressListener import com.casic.electric.detector.callback.ILocationListener -object LocationHub { - private const val kTag = "LocationHub" +class LocationHub constructor(context: Context) { - fun getCurrentLocation(context: Context, listener: ILocationListener) { - val locationClient = AMapLocationClient(context) + private val kTag = "LocationHub" + private val locationClient by lazy { AMapLocationClient(context) } + private val codeSearch by lazy { GeocodeSearch(context) } + + fun getCurrentLocation(isOnceLocation: Boolean, listener: ILocationListener) { val locationOption = AMapLocationClientOption() locationOption.locationMode = AMapLocationClientOption.AMapLocationMode.Hight_Accuracy - locationOption.isOnceLocation = true + locationOption.isOnceLocation = isOnceLocation locationClient.setLocationOption(locationOption) locationClient.setLocationListener { if (it.errorCode == 0) { @@ -36,9 +38,8 @@ locationClient.startLocation() } - fun antiCodingLocation(context: Context, location: Location, listener: IAddressListener) { + fun antiCodingLocation(location: Location, listener: IAddressListener) { try { - val codeSearch = GeocodeSearch(context) // 第一个参数表示一个LatLonPoint,第二参数表示范围多少米,第三个参数表示是火系坐标系还是GPS原生坐标系 val query = RegeocodeQuery( LatLonPoint(location.latitude, location.longitude), 10f, GeocodeSearch.AMAP @@ -55,4 +56,8 @@ e.printStackTrace() } } + + fun stopLocation() { + locationClient.stopLocation() + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt b/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt index aa1bdeb..e3d3289 100644 --- a/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt @@ -1,7 +1,6 @@ package com.casic.electric.detector.view import android.content.Context -import android.graphics.Color import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -12,10 +11,10 @@ import com.bumptech.glide.Glide import com.casic.electric.detector.R import com.casic.electric.detector.databinding.ActivityBigImageBinding +import com.casic.electric.detector.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class BigImageActivity : KotlinBaseActivity() { @@ -24,20 +23,12 @@ } override fun setupTopBarLayout() { - ImmerseStatusBarUtil.setColor(this, Color.BLACK) + binding.rootView.initImmersionBar(this, false, R.color.black) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - val index: Int = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return @@ -62,6 +53,14 @@ }) } + override fun observeRequestState() { + + } + + override fun initEvent() { + + } + inner class BigImageAdapter( private val context: Context, private val data: ArrayList ) : PagerAdapter() { diff --git a/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt b/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt index d3a89ca..6510104 100644 --- a/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt @@ -29,15 +29,15 @@ import com.casic.electric.detector.extensions.* import com.casic.electric.detector.utils.* import com.casic.electric.detector.vm.TaskViewModel -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia import com.luck.picture.lib.interfaces.OnResultCallbackListener import com.pengxh.kt.lite.extensions.* +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -53,7 +53,8 @@ private val context: Context = this@InstallLabelActivity private val gpioManager by lazy { GpioManager() } private val calendar by lazy { Calendar.getInstance() } - private val realPaths: ArrayList = ArrayList() //真实图片路径 + private val locationHub by lazy { LocationHub(this) } + private val realPaths = ArrayList() //真实图片路径 private var soundResId = 0 private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var soundPool: SoundPool @@ -67,12 +68,6 @@ override fun setupTopBarLayout() { binding.titleInclude.titleView.text = "安装新标识器" binding.titleInclude.titleView.setTextColor(R.color.themeColor.convertColor(this)) - - ImmersionBar.with(this) - .statusBarDarkFont(true) - .statusBarColor(R.color.mainBackground) - .init() - initLayoutImmersionBar(binding.rootView) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -126,7 +121,7 @@ binding.markerAttrInclude.remarkView3.setText("remarkView3".getDefaultValue()) //初始化图片九宫格 - imageAdapter = EditableImageAdapter(this, 3, 3f) + imageAdapter = EditableImageAdapter(this, 3, 3) binding.cameraInclude.addImageRecyclerView.adapter = imageAdapter taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] @@ -332,7 +327,7 @@ binding.markerAttrInclude.installTimeView.text = System.currentTimeMillis().timestampToCompleteDate() - LocationHub.getCurrentLocation(this, object : ILocationListener { + locationHub.getCurrentLocation(true, object : ILocationListener { override fun onAMapLocationGet(location: AMapLocation?) { if (location != null) { binding.markerAttrInclude.lngView.text = location.longitude.toString() @@ -518,8 +513,8 @@ weakReferenceHandler.postDelayed({ try { // 发送读标识器或搜索信号 - outputStream?.write("2".toByteArray()) - outputStream?.flush() + out.write("2".toByteArray()) + out.flush() } catch (e: IOException) { e.printStackTrace() } @@ -527,7 +522,7 @@ } } - override fun onDataReceived(buffer: ByteArray?, size: Int) { + override fun onDataReceived(buffer: ByteArray) { Log.d(kTag, "onDataReceived => " + buffer.contentToString()) if (buffer != null) { val message = weakReferenceHandler.obtainMessage() diff --git a/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt b/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt index 5bc2ac8..286bf4a 100644 --- a/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt @@ -24,7 +24,6 @@ import com.casic.electric.detector.extensions.* import com.casic.electric.detector.utils.* import com.casic.electric.detector.vm.TaskViewModel -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -33,9 +32,10 @@ import com.pengxh.kt.lite.extensions.isNetworkConnected import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -65,12 +65,6 @@ override fun setupTopBarLayout() { binding.titleInclude.titleView.text = "安装新电子标签" binding.titleInclude.titleView.setTextColor(R.color.themeColor.convertColor(this)) - - ImmersionBar.with(this) - .statusBarDarkFont(true) - .statusBarColor(R.color.mainBackground) - .init() - initLayoutImmersionBar(binding.rootView) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -103,7 +97,7 @@ binding.objectAttrInclude.objectRemarkView3.setText("objectRemarkView3".getDefaultValue()) //初始化图片九宫格 - imageAdapter = EditableImageAdapter(this, 3, 3f) + imageAdapter = EditableImageAdapter(this, 3, 3) binding.cameraInclude.addImageRecyclerView.adapter = imageAdapter taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] @@ -308,8 +302,8 @@ weakReferenceHandler.postDelayed({ try { // 发送读标识器或搜索信号 - outputStream?.write("2".toByteArray()) - outputStream?.flush() + out.write("2".toByteArray()) + out.flush() } catch (e: IOException) { e.printStackTrace() } @@ -317,7 +311,7 @@ } } - override fun onDataReceived(buffer: ByteArray?, size: Int) { + override fun onDataReceived(buffer: ByteArray) { if (buffer != null) { val message = weakReferenceHandler.obtainMessage() message.what = 2023081702 diff --git a/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt b/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt index 44d56ef..9c98b5f 100644 --- a/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt @@ -1,36 +1,29 @@ package com.casic.electric.detector.view import android.os.Bundle -import android.util.Log import androidx.lifecycle.ViewModelProvider import com.amap.api.navi.NaviSetting import com.casic.electric.detector.databinding.ActivityLoginBinding -import com.casic.electric.detector.extensions.initLayoutImmersionBar -import com.casic.electric.detector.utils.GpioManager -import com.casic.electric.detector.utils.LoadingDialogHub import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.vm.UserViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.getScreenHeight -import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog class LoginActivity : KotlinBaseActivity() { private val kTag = "LoginActivity" private lateinit var userViewModel: UserViewModel - private val gpioManager by lazy { GpioManager() } override fun initViewBinding(): ActivityLoginBinding { return ActivityLoginBinding.inflate(layoutInflater) } override fun initOnCreate(savedInstanceState: Bundle?) { - gpioManager.setGpioLow("18") //先把导航隐私政策声明,后面导航会用到 NaviSetting.updatePrivacyShow(this, true, true) NaviSetting.updatePrivacyAgree(this, true) @@ -60,11 +53,8 @@ val serversIp = binding.serversIpView.text.toString() val serversPort = binding.serversPortView.text.toString() if (account.isBlank() || password.isBlank() || serversIp.isBlank() || serversPort.isBlank()) { - AlertMessageDialog.Builder() - .setContext(this) - .setTitle("账号登录") - .setMessage("信息不能为空哦!") - .setPositiveButton("知道了") + AlertMessageDialog.Builder().setContext(this).setTitle("账号登录") + .setMessage("信息不能为空哦!").setPositiveButton("知道了") .setOnDialogButtonClickListener(object : AlertMessageDialog.OnDialogButtonClickListener { override fun onConfirmClick() { @@ -102,9 +92,6 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(true).init() - initLayoutImmersionBar(binding.rootView) - - Log.d(kTag, "setupTopBarLayout => [${getScreenWidth()}, ${getScreenHeight()}]") } override fun onResume() { diff --git a/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt b/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt index 36a8d55..a0a4aac 100644 --- a/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt @@ -1,15 +1,21 @@ package com.casic.electric.detector.view +import android.annotation.SuppressLint import android.app.AlertDialog +import android.app.Dialog import android.content.Context -import android.content.Intent import android.graphics.Color import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable +import android.media.AudioAttributes +import android.media.SoundPool import android.os.Bundle -import android.os.PowerManager -import android.provider.Settings +import android.os.CountDownTimer +import android.util.Log import android.view.KeyEvent +import android.view.View +import android.view.animation.Animation +import android.view.animation.RotateAnimation import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import com.amap.api.location.AMapLocation @@ -21,6 +27,8 @@ import com.amap.api.maps.model.LatLngBounds import com.amap.api.maps.model.MyLocationStyle import com.casic.electric.detector.R +import com.casic.electric.detector.adapter.EditableImageAdapter +import com.casic.electric.detector.base.SerialPortActivity import com.casic.electric.detector.bean.LabelBean import com.casic.electric.detector.bean.SmallLabelBean import com.casic.electric.detector.bean.TaskBean @@ -29,83 +37,109 @@ import com.casic.electric.detector.cluster.ClusterOverlay import com.casic.electric.detector.cluster.RegionItem import com.casic.electric.detector.databinding.ActivityMainBinding +import com.casic.electric.detector.databinding.DialogInstallMarkerBinding +import com.casic.electric.detector.databinding.DialogInstallSmallMarkerBinding +import com.casic.electric.detector.databinding.DialogSearchMarkerBinding import com.casic.electric.detector.extensions.appendExcelDownloadUrl import com.casic.electric.detector.extensions.drawCircle -import com.casic.electric.detector.extensions.initLayoutImmersionBar +import com.casic.electric.detector.extensions.hexToString +import com.casic.electric.detector.extensions.initImmersionBar +import com.casic.electric.detector.extensions.isNumber +import com.casic.electric.detector.extensions.toHex import com.casic.electric.detector.utils.DataBaseManager import com.casic.electric.detector.utils.ExcelHub -import com.casic.electric.detector.utils.LoadingDialogHub +import com.casic.electric.detector.utils.GpioManager import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.LocationHub import com.casic.electric.detector.utils.RouteOnMap import com.casic.electric.detector.vm.TaskViewModel import com.casic.electric.detector.widgets.QueryMarkerDialog import com.casic.electric.detector.widgets.SamplePopupWindow -import com.gyf.immersionbar.ImmersionBar -import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.callback.OnDownloadListener +import com.google.gson.Gson +import com.pengxh.kt.lite.extensions.binding import com.pengxh.kt.lite.extensions.createDownloadFileDir -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.dp2px +import com.pengxh.kt.lite.extensions.initDialogLayoutParams import com.pengxh.kt.lite.extensions.isNetworkConnected import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.toJson +import com.pengxh.kt.lite.utils.FileDownloadManager +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog +import com.pengxh.kt.lite.widget.dialog.AlertInputDialog +import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File +import java.text.DecimalFormat +import java.util.Calendar +import java.util.Timer +import java.util.TimerTask -class MainActivity : KotlinBaseActivity() { +@SuppressLint("all") +class MainActivity : SerialPortActivity() { private val kTag = "MainActivity" - private val context: Context = this@MainActivity + private val context = this@MainActivity + private val gpioManager by lazy { GpioManager() } private val samplePopupWindow by lazy { SamplePopupWindow(this) } + private val gson by lazy { Gson() } + private val locationHub by lazy { LocationHub(this) } + private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } + private val backDrawables by lazy { HashMap() } + private val installMarkerDialog by lazy { InstallMarkerDialog(this) } + private val installSmallMarkerDialog by lazy { InstallSmallMarkerDialog(this) } + private val searchDialog by lazy { SearchMarkerDialog(this) } private var clickTime: Long = 0 - private lateinit var wakeLock: PowerManager.WakeLock - private lateinit var aMap: AMap - private lateinit var taskViewModel: TaskViewModel - private lateinit var taskBean: TaskBean - private var latitude: Double = 0.0 - private var longitude: Double = 0.0 private var labels = ArrayList() private var smallLabels = ArrayList() private var clusterOverlay: ClusterOverlay? = null - private val backDrawables = HashMap() - private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } + private var latitude: Double = 0.0 + private var longitude: Double = 0.0 + private var isFreeTask = false + private var ids = ArrayList() + private var signalTask: TimerTask? = null + private var searchMarkerTimer: Timer? = null + private lateinit var aMap: AMap + private lateinit var taskBean: TaskBean + private lateinit var taskId: String + + /***inner class 需要用到*****start*/ + private val taskViewModel by lazy { ViewModelProvider(this)[TaskViewModel::class.java] } + 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 var soundResourceId = 0 + private var slowSoundResourceId = 0 + private var fastSoundResourceId = 0 + + /***inner class 需要用到*****end*/ override fun initViewBinding(): ActivityMainBinding { return ActivityMainBinding.inflate(layoutInflater) } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).statusBarColor(R.color.themeColor).init() - initLayoutImmersionBar(binding.rootView) - } - - override fun observeRequestState() { - + binding.rootView.initImmersionBar(this, false, R.color.themeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { - val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager - wakeLock = powerManager.run { - newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this@MainActivity.localClassName).apply { - acquire(60 * 60 * 1000L) - } - } + soundResourceId = soundPool.load(this, R.raw.ring3, 1) + slowSoundResourceId = soundPool.load(this, R.raw.ring4, 1) + fastSoundResourceId = soundPool.load(this, R.raw.ring2, 1) + //地图初始化 initMapConfig(savedInstanceState) samplePopupWindow.setPopupMenuItem(LocaleConstant.POPUP_TITLES) samplePopupWindow.setBackgroundDrawable(null) - taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] + //task网络请求监听 taskViewModel.markerFileResult.observe(this) { if (it.success == "true") { //清空之前的数据 @@ -122,11 +156,13 @@ val smallLabelDownloadUrl = urlArray[1].appendExcelDownloadUrl() //下载标识器 - labelDownloadUrl.downloadFile( - createDownloadFileDir().toString(), object : OnDownloadListener { - override fun onDownloadEnd(file: File?) { + FileDownloadManager.Builder().setDownloadFileSource(labelDownloadUrl) + .setFileSuffix("xls").setFileSaveDirectory(createDownloadFileDir()) + .setOnFileDownloadListener(object : + FileDownloadManager.OnFileDownloadListener { + override fun onDownloadEnd(file: File) { lifecycleScope.launch { - labels = ExcelHub.readLabel(file?.absolutePath) + labels = ExcelHub.readLabel(file.absolutePath) withContext(Dispatchers.IO) { labels.forEach { label -> DataBaseManager.get.insertLabel(label) @@ -137,21 +173,23 @@ } } - override fun onDownloadStart(totalBytes: Long) { + override fun onFailure(throwable: Throwable) { } - override fun onProgressChanged(currentBytes: Long) { + override fun onProgressChanged(progress: Int) { } - }) + }).build().start() //下载附属标识器 - smallLabelDownloadUrl.downloadFile( - createDownloadFileDir().toString(), object : OnDownloadListener { - override fun onDownloadEnd(file: File?) { + FileDownloadManager.Builder().setDownloadFileSource(smallLabelDownloadUrl) + .setFileSuffix("xls").setFileSaveDirectory(createDownloadFileDir()) + .setOnFileDownloadListener(object : + FileDownloadManager.OnFileDownloadListener { + override fun onDownloadEnd(file: File) { lifecycleScope.launch { - smallLabels = ExcelHub.readSmallLabel(file?.absolutePath) + smallLabels = ExcelHub.readSmallLabel(file.absolutePath) withContext(Dispatchers.IO) { smallLabels.forEach { label -> DataBaseManager.get.insertSmallLabel(label) @@ -160,14 +198,14 @@ } } - override fun onDownloadStart(totalBytes: Long) { + override fun onFailure(throwable: Throwable) { } - override fun onProgressChanged(currentBytes: Long) { + override fun onProgressChanged(progress: Int) { } - }) + }).build().start() } } } @@ -175,11 +213,8 @@ // if (it.success == "true") { // //清空之前的数据 // DataBaseManager.get.clearTasks() -// AlertMessageDialog.Builder() -// .setContext(this) -// .setTitle("温馨提示") -// .setMessage("您有${it.message.size}个新任务!") -// .setPositiveButton("知道了") +// AlertMessageDialog.Builder().setContext(this).setTitle("温馨提示") +// .setMessage("您有${it.message.size}个新任务!").setPositiveButton("知道了") // .setOnDialogButtonClickListener(object : // AlertMessageDialog.OnDialogButtonClickListener { // override fun onConfirmClick() { @@ -188,19 +223,24 @@ // }).build().show() // } // } + taskViewModel.freeTaskResult.observe(this) { taskId = it } + taskViewModel.uploadTaskMarkerResult.observe(this) { + "自由巡检任务已完成".show(this) + ids.clear() + } } override fun initEvent() { binding.rightImageView.setOnClickListener { - CoroutineScope(Dispatchers.Main).launch { + lifecycleScope.launch(Dispatchers.Main) { val labels = withContext(Dispatchers.IO) { DataBaseManager.get.queryLabelById("0") } if (labels.isNotEmpty()) { samplePopupWindow.setShowPosition(4) } - val x = binding.rightImageView.width - samplePopupWindow.width - 1f.dp2px(context) - samplePopupWindow.showAsDropDown(binding.rightImageView, x, 1f.dp2px(context)) + val x = binding.rightImageView.width - samplePopupWindow.width - 1.dp2px(context) + samplePopupWindow.showAsDropDown(binding.rightImageView, x, 1.dp2px(context)) } } @@ -219,35 +259,33 @@ //安装。上传,然后存入本地库 binding.installButton.setOnClickListener { - AlertControlDialog.Builder() - .setContext(context) - .setTitle("提示") - .setMessage("请选择安装对象") - .setPositiveButton("标识器") - .setNegativeButton("电子标签") - .setOnDialogButtonClickListener(object : + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("请选择安装对象").setPositiveButton("标识器") + .setNegativeButton("电子标签").setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { //标识器 - navigatePageTo() + /** + * 改为Dialog方式,避免频繁打开/关闭串口 + * */ + installMarkerDialog.show() } override fun onCancelClick() { //电子标签 - navigatePageTo() + /** + * 改为Dialog方式,避免频繁打开/关闭串口 + * */ + installSmallMarkerDialog.show() } }).build().show() } //查看 binding.viewButton.setOnClickListener { - QueryMarkerDialog.Builder() - .setContext(this) - .setTitle("查看标识器") - .setConditionArray(LocaleConstant.CONDITION_ARRAY) - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : + QueryMarkerDialog.Builder().setContext(this).setTitle("查看标识器") + .setConditionArray(LocaleConstant.CONDITION_ARRAY).setNegativeButton("取消") + .setPositiveButton("确定").setOnDialogButtonClickListener(object : QueryMarkerDialog.OnDialogButtonClickListener { override fun onConfirmClick( selectedCondition: String, vararg contentValue: String @@ -310,30 +348,25 @@ // arrayList.add("任务${index + 1}:${taskBean.taskId},${taskBean.desc}") // } // -// BottomActionSheet.Builder() -// .setContext(this) -// .setItemTextColor(Color.BLUE) +// BottomActionSheet.Builder().setContext(this).setItemTextColor(Color.BLUE) // .setActionItemTitle(arrayList) // .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { // override fun onActionItemClick(position: Int) { // val taskBean = task[position] // SaveKeyValues.putValue(LocaleConstant.TASK_ID, taskBean.taskId) -// AlertControlDialog.Builder() -// .setContext(context) -// .setTitle("提示") -// .setMessage("请选择操作方式") -// .setPositiveButton("执行工单") +// AlertControlDialog.Builder().setContext(context).setTitle("提示") +// .setMessage("请选择操作方式").setPositiveButton("执行工单") // .setNegativeButton("提交工单") // .setOnDialogButtonClickListener(object : // AlertControlDialog.OnDialogButtonClickListener { // override fun onConfirmClick() { // detectRedrawGraphic(taskBean.taskId) +// +// val latLng = LatLng( +// taskBean.lat.toDouble(), taskBean.lng.toDouble() +// ) // aMap.moveCamera( -// CameraUpdateFactory.newLatLngZoom( -// LatLng( -// taskBean.lat.toDouble(), taskBean.lng.toDouble() -// ), 15f -// ) +// CameraUpdateFactory.newLatLngZoom(latLng, 16f) // ) // uploadTask(taskBean.taskId, "1") // } @@ -345,15 +378,12 @@ // } // }).build().show() // } else { -// AlertMessageDialog.Builder() -// .setContext(this) -// .setTitle("温馨提示") -// .setMessage("现有任务已完成,请点击右上角菜单按钮下载新工单!") -// .setPositiveButton("知道了") -// .setOnDialogButtonClickListener(object : +// AlertMessageDialog.Builder().setContext(this).setTitle("温馨提示") +// .setMessage("现有任务已完成,请点击右上角菜单下载新工单或者开始自由巡检") +// .setPositiveButton("知道了").setOnDialogButtonClickListener(object : // AlertMessageDialog.OnDialogButtonClickListener { // override fun onConfirmClick() { -// +// startFreeTask() // } // }).build().show() // } @@ -361,7 +391,118 @@ //探测 binding.detectionButton.setOnClickListener { -// navigatePageTo() + /** + * 改为Dialog方式,避免频繁打开/关闭串口 + * */ + searchDialog.show() + } + + //自由巡检 + binding.stopFreeTaskButton.setOnLongClickListener { + AlertMessageDialog.Builder().setContext(this).setTitle("温馨提示") + .setMessage("是否确定结束此次自由巡检任务?").setPositiveButton("是") + .setOnDialogButtonClickListener(object : + AlertMessageDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + isFreeTask = false + soundPool.autoPause() + + //降低串口电位 + gpioManager.setGpioLow("18") + + taskViewModel.uploadTaskMarker(taskId, ids) + binding.stopFreeTaskButton.visibility = View.GONE + } + }).build().show() + true + } + } + + private fun startFreeTask() { + AlertInputDialog.Builder().setContext(this).setTitle("新建自由巡检任务") + .setHintMessage("请输入自由巡检任务简要描述").setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : AlertInputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String + taskViewModel.createFreeTask(userId, value) + + //调高串口电位 + gpioManager.setGpioHigh("18") + + soundPool.play(soundResourceId, 1f, 1f, 0, -1, 1f) + isFreeTask = true + //自由巡检 + signalTask = object : TimerTask() { + override fun run() { + out.write('2'.code) + out.flush() + } + } + searchMarkerTimer = Timer() + searchMarkerTimer?.apply { + schedule(signalTask, 0, 100) + } + + binding.stopFreeTaskButton.visibility = View.VISIBLE + } + + override fun onCancelClick() {} + }).build().show() + } + + override fun onDataReceived(buffer: ByteArray) { + val hex = buffer.toHex() + Log.d(kTag, "$kTag => $hex") + if (searchDialog.isDetectMarker) { + searchDialog.bindingValue(hex) +// } else if (installMarkerDialog.isReadMarker) { +// val markerId = hex.take(20).hexToString() +// if (markerId.isNumber()) { +// installMarkerDialog.bindingValue(markerId) +// } +// } else if (installSmallMarkerDialog.isReadMarker) { +// val markerId = hex.take(20).hexToString() +// if (markerId.isNumber()) { +// installSmallMarkerDialog.bindingValue(markerId) +// } + } else if (isFreeTask) { + val markerId = hex.take(20).hexToString() + if (markerId.isNumber()) { + "标识器${markerId}已探测".show(this) + ids.add(markerId) + } + } + } + + override fun observeRequestState() { + taskViewModel.loadState.observe(this) { + when (it) { + LoadState.Loading -> { + if (installMarkerDialog.isInstallMarker || installSmallMarkerDialog.isInstallMarker) { + LoadingDialogHub.show(this, "标识器安装中,请稍后...") + } else if (searchDialog.isDetectMarker) { + searchDialog.taskBean?.apply { + "标识器${this.markerId}已探测!".show(context) +// DataBaseManager.get.updateTaskLabel(this) + } + } else { + LoadingDialogHub.show(this, "提交工单中,请稍后") + } + } + + else -> { + if (installMarkerDialog.isInstallMarker) { + installMarkerDialog.dismiss() + installMarkerDialog.isInstallMarker = false + } else if (installSmallMarkerDialog.isInstallMarker) { + installSmallMarkerDialog.dismiss() + installSmallMarkerDialog.isInstallMarker = false + } + LoadingDialogHub.dismiss() + } + } + detectRedrawGraphic(taskBean.taskId) } } @@ -375,6 +516,7 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜 //显示定位小蓝点 val locationStyle = MyLocationStyle() locationStyle.interval(2000) @@ -387,7 +529,7 @@ longitude = it.longitude latitude = it.latitude //经纬度逆编码 - LocationHub.antiCodingLocation(context, it) { address -> + locationHub.antiCodingLocation(it) { address -> binding.currentLocationView.text = address } } @@ -417,7 +559,7 @@ } private fun moveToCurrentLocation() { - LocationHub.getCurrentLocation(this, object : ILocationListener { + locationHub.getCurrentLocation(true, object : ILocationListener { override fun onAMapLocationGet(location: AMapLocation?) { if (location != null) { aMap.moveCamera( @@ -432,46 +574,35 @@ }) } - //更新数据 - private fun updateLabels() { - AlertControlDialog.Builder() - .setContext(this) - .setTitle("提示") - .setMessage("是否更新数据?") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onConfirmClick() { - if (isNetworkConnected()) { - val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") - val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") - - LoadingDialogHub.show(this@MainActivity, "获取标识器信息中,请稍后") - //TODO 设计如此,都传companyId - taskViewModel.getMarkerFile(companyId.toString(), companyId.toString()) - } else { - NoNetworkDialog.Builder() - .setContext(context) - .setOnDialogButtonClickListener(object : - NoNetworkDialog.OnDialogButtonClickListener { - override fun onButtonClick() { - val intent = Intent(Settings.ACTION_SETTINGS) - startActivity(intent) - } - }).build().show() - } - } - - override fun onCancelClick() { - - } - }).build().show() - } +// private fun saveTaskInformation(it: TaskModel) { +// val userName = SaveKeyValues.getValue(LocaleConstant.USER_NAME, "") as String +// if (it.message.size > 0) { +// it.message.forEach { messageModel -> +// val count = DataBaseManager.get.countTaskById(messageModel.id.toString()) +// if (count == 0) { +// messageModel.taskDetailInfos.forEach { info -> +// DataBaseManager.get.insertTaskInformation( +// userName, +// messageModel.description, +// info.taskId.toString(), +// info.id.toString(), +// info.markerId.toString(), +// info.markerIdReal.toString(), +// info.longitude.toString(), +// info.latitude.toString(), +// messageModel.status +// ) +// } +// } +// } +// "工单下载成功!".show(context) +// } +// } private fun showLabelsOnMap() { clusterOverlay?.onDestroy() val clusterItems = ArrayList() + labels.forEach { val latLng = LatLng(it.latitude.toDouble(), it.longitude.toDouble(), false) val regionItem = RegionItem(latLng, it.markerId.toString()) @@ -480,7 +611,7 @@ clusterOverlay = ClusterOverlay(context, aMap, clusterItems, regionRadius) clusterOverlay?.setClusterRender { clusterNum -> - val radius = 80f.dp2px(context) + val radius = 80.dp2px(context) if (clusterNum == 0) { var bitmapDrawable = backDrawables[0] if (bitmapDrawable == null) { @@ -546,9 +677,7 @@ val latLngBounds = builder.build() aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 0)) - BottomActionSheet.Builder() - .setContext(this) - .setItemTextColor(Color.BLUE) + BottomActionSheet.Builder().setContext(this).setItemTextColor(Color.BLUE) .setActionItemTitle(listOf("标识器信息", "附属电子标签信息", "到这里去")) .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { override fun onActionItemClick(position: Int) { @@ -578,12 +707,7 @@ showElectricMarkers(electricMarkers) } - 2 -> { - RouteOnMap.startNavigation( - context, item.tag, - LatLng(item.position.latitude, item.position.longitude) - ) - } + 2 -> RouteOnMap.startNavigation(context, item.tag, latLng) } } }).build().show() @@ -591,14 +715,74 @@ } private fun showElectricMarkers(markers: ArrayList) { - AlertDialog.Builder(context) - .setIcon(R.mipmap.ic_launcher) - .setTitle("电子标签列表") + AlertDialog.Builder(context).setIcon(R.mipmap.ic_launcher).setTitle("电子标签列表") .setSingleChoiceItems(markers.toTypedArray(), -1) { _, which -> navigatePageTo(markers[which]) }.show() } + private fun detectRedrawGraphic(taskId: String) { +// val tasks = DataBaseManager.get.queryTaskById(taskId) +// if (tasks.isNotEmpty()) { +// tasks.forEach { +// val latLng = LatLng(it.lat.toDouble(), it.lng.toDouble()) +// val otMarkerOptions = MarkerOptions() +// otMarkerOptions.position(latLng) +// otMarkerOptions.visible(true) // 设置可见 +// if (it.state == "未开始") { +// otMarkerOptions.icon( +// BitmapDescriptorFactory.fromBitmap( +// BitmapFactory.decodeResource(resources, R.mipmap.label_red1) +// ) +// ).period(99).title("工单标识器").snippet(it.markerId) +// } else { +// otMarkerOptions.icon( +// BitmapDescriptorFactory.fromBitmap( +// BitmapFactory.decodeResource(resources, R.mipmap.label_blue1) +// ) +// ).period(99).title("工单标识器").snippet(it.markerId) +// } +// aMap.addMarker(otMarkerOptions) +// } +// } + showLabelsOnMap() + } + + private fun uploadTask(taskId: String?, state: String) { + if (isNetworkConnected()) { + val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String + taskViewModel.uploadTask(userId, taskId, state) + } else { + "网络连接已断开,请检查".show(this) + } + } + + //更新数据 + private fun updateLabels() { + AlertControlDialog.Builder().setContext(this).setTitle("提示").setMessage("是否更新数据?") + .setNegativeButton("取消").setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + if (isNetworkConnected()) { + val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") + + LoadingDialogHub.show(this@MainActivity, "获取标识器信息中,请稍后") + /** + * 后台设计如此,都传companyId + * */ + taskViewModel.getMarkerFile(companyId.toString(), companyId.toString()) + } else { + "网络连接已断开,请检查".show(context) + } + } + + override fun onCancelClick() { + + } + }).build().show() + } + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { return if (keyCode == KeyEvent.KEYCODE_BACK) { if (System.currentTimeMillis() - clickTime > 2000) { @@ -643,8 +827,270 @@ } override fun onDestroy() { - wakeLock.release() super.onDestroy() binding.mapView.onDestroy() + signalTask?.cancel() + searchMarkerTimer?.cancel() + soundPool.release() + locationHub.stopLocation() + //降低串口电位 + gpioManager.setGpioLow("18") + } + + /**安装标识器对话框******************************************************************************/ + inner class InstallMarkerDialog(context: Context) : Dialog(context) { + + private val binding: DialogInstallMarkerBinding by binding() + private val calendar by lazy { Calendar.getInstance() } + private val realPaths = ArrayList() //真实图片路径 + private lateinit var imageAdapter: EditableImageAdapter + + var isReadMarker = false + var isInstallMarker = false + } + + /**安装小标签对话框******************************************************************************/ + inner class InstallSmallMarkerDialog(context: Context) : Dialog(context) { + + private val binding: DialogInstallSmallMarkerBinding by binding() + private val calendar by lazy { Calendar.getInstance() } + private val realPaths = ArrayList() //真实图片路径 + private lateinit var imageAdapter: EditableImageAdapter + + var isReadMarker = false + var isInstallMarker = false + } + + /**探测标识器对话框******************************************************************************/ + inner class SearchMarkerDialog(context: Context) : Dialog(context) { + + private val binding: DialogSearchMarkerBinding by binding() + private val decimal by lazy { DecimalFormat("0.0") } + private val degreeCache by lazy { HashMap() } + private var isPlaying = false + private var markerId = "" + private lateinit var searchMarkerTimer: Timer + private lateinit var signalTask: TimerTask + private lateinit var energyTask: TimerTask + private lateinit var countDownTimer: CountDownTimer + + var isDetectMarker = false + var taskBean: TaskBean? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.initDialogLayoutParams(1f) + binding.depthButton.setOnClickListener { + signalTask.cancel() + energyTask.cancel() + searchMarkerTimer.cancel() + + out.write('3'.code) +// val result = DataBaseManager.get.queryLabelById(markerId) +// if (result.isNotEmpty()) { +// val tag = when (result.first().identifierType) { +// "EM30" -> '7' +// "EM50" -> '8' +// "EM14" -> '9' +// else -> '1' +// } +// if (tag == '1') { +// "此标识器无法读取埋深!".show(context) +// } else { +// // 发送读取标识器埋设深度指令 +// LoadingDialogHub.show(this@MainActivity, "正在测距,请稍后...") +// out.write(tag.code) +// out.flush() +// countDownTimer = object : CountDownTimer(15 * 1000, 1000) { +// override fun onTick(millisUntilFinished: Long) { +// +// } +// +// override fun onFinish() { +// LoadingDialogHub.dismiss() +// "探测此标识器深度超时,请重试".show(context) +// initTimer() +// } +// } +// countDownTimer.start() +// } +// } else { +// "标识器未安装,安装成功后才可读取埋深!".show(context) +// } + } + + binding.markerInfoButton.setOnClickListener { + //查库 + val result = DataBaseManager.get.queryLabelById(markerId) + if (result.isNotEmpty()) { +// context.navigatePageTo(result.first().toJson()) + } else { +// context.navigatePageTo(markerId) + } + } + } + + override fun onStart() { + super.onStart() + //调高串口电位 + gpioManager.setGpioHigh("18") + + initTimer() + + isDetectMarker = true + + //角度 + degreeCache["lastDegree"] = 0f + } + + fun bindingValue(hex: String) { + if (hex.startsWith("4E")) { + try { + //4E转为String为N,代表能量值 + //用能量值转动表盘 + val energyResponse = hex.take(10).hexToString() + val energy = energyResponse.substring(1).toInt() + if (energy >= 4000) { + isPlaying = if (!isPlaying) { + soundPool.play(fastSoundResourceId, 1f, 1f, 0, 0, 1f) + true + } else { + soundPool.pause(fastSoundResourceId) + false + } + } else { + isPlaying = if (!isPlaying) { + soundPool.play(slowSoundResourceId, 1f, 1f, 0, 0, 1f) + true + } else { + soundPool.pause(slowSoundResourceId) + false + } + } + + binding.resultTextView.text = "信号能量值:${energyResponse}" + + //转换为转动的角度 + val degree = (energy.toFloat() / (50 * 100)) * 180 + binding.energyValueView.text = decimal.format(degree) + + degreeCache["lastDegree"]?.apply { + val animation = RotateAnimation( + this, degree, + Animation.RELATIVE_TO_SELF, 0.5f, + Animation.RELATIVE_TO_SELF, 0.5f + ) + animation.duration = 0 + animation.fillAfter = true + binding.needleView.startAnimation(animation) + } + + //保存旋转后的角度 + degreeCache["lastDegree"] = degree + + if (energy <= 700) {//18° + binding.energyTipsView.text = "标识器信号较弱,可能距离较远" + binding.energyTipsView.setTextColor(Color.parseColor("#8D1717")) + binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_red) + + binding.depthButton.isEnabled = false + binding.depthButton.setTextColor(Color.parseColor("#CCCCCC")) + binding.depthButton.setBackgroundResource(R.mipmap.left_button_disable) + binding.markerInfoButton.isEnabled = false + binding.markerInfoButton.setTextColor(Color.parseColor("#CCCCCC")) + binding.markerInfoButton.setBackgroundResource(R.mipmap.right_button_disable) + + binding.searchResultView.text = "未检测到标识器" + binding.searchResultView.setTextColor(Color.parseColor("#8D1717")) + binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_red) + } else if (energy >= 4100) {//148° + binding.energyTipsView.text = "标识器信号极强,可能在正下方" + binding.energyTipsView.setTextColor(Color.parseColor("#428d00")) + binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_green) + } else {//[18°,148°] + binding.energyTipsView.text = "已靠近标识器,请继续移动位置" + binding.energyTipsView.setTextColor(Color.parseColor("#8C5700")) + binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_yellow) + } + } catch (e: NumberFormatException) { + e.printStackTrace() + } + } else if (hex.startsWith("53")) { + LoadingDialogHub.dismiss() + countDownTimer.cancel() + try { + val depthResponse = hex.take(10).hexToString() + val depth = depthResponse.drop(2).toInt() + AlertMessageDialog.Builder().setContext(context).setTitle("温馨提示") + .setMessage("标识器埋深:${depth}厘米").setPositiveButton("知道了") + .setOnDialogButtonClickListener(object : + AlertMessageDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + initTimer() + } + }).build().show() + } catch (e: NumberFormatException) { + e.printStackTrace() + } + } else { + val id = hex.take(20).hexToString() + if (id.isNumber()) { + markerId = id + + binding.depthButton.isEnabled = true + binding.depthButton.setTextColor(Color.WHITE) + binding.depthButton.setBackgroundResource(R.mipmap.left_button_enable) + binding.markerInfoButton.isEnabled = true + binding.markerInfoButton.setTextColor(Color.WHITE) + binding.markerInfoButton.setBackgroundResource(R.mipmap.right_button_enable) + + binding.searchResultView.text = "已检测到标识器" + binding.searchResultView.setTextColor(Color.parseColor("#428d00")) + binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_green) + + //自动上传标识器 +// taskBean = DataBaseManager.get.queryTaskLabelByIdAndState(markerId, "未开始") +// taskBean?.apply { +// /** +// * 此taskCode是 [com.casic.detector.model.TaskModel.MessageModel.TaskDetailInfosModel] 里面的主键,也就是这个标签在数据库里面的主键 +// * */ +// taskViewModel.uploadMarker(taskCode) +// } + } + } + } + + private fun initTimer() { + searchMarkerTimer = Timer() + + signalTask = object : TimerTask() { + override fun run() { + out.write('2'.code) + out.flush() + } + } + + energyTask = object : TimerTask() { + override fun run() { + out.write('6'.code) + out.flush() + } + } + + //错开信号和能量定时器 + searchMarkerTimer.schedule(signalTask, 0, 201) + searchMarkerTimer.schedule(energyTask, 0, 251) + } + + override fun dismiss() { + signalTask.cancel() + energyTask.cancel() + searchMarkerTimer.cancel() + //降低串口电位 + gpioManager.setGpioLow("18") + isDetectMarker = false + soundPool.autoPause() + super.dismiss() + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt b/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt index 6a00429..cbd6137 100644 --- a/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt @@ -13,18 +13,16 @@ import com.casic.electric.detector.R import com.casic.electric.detector.databinding.ActivityVersionControlBinding import com.casic.electric.detector.extensions.appendDownloadUrl -import com.casic.electric.detector.extensions.initLayoutImmersionBar +import com.casic.electric.detector.extensions.initImmersionBar import com.casic.electric.detector.utils.FileType -import com.casic.electric.detector.utils.LoadingDialogHub import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.vm.VersionViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.createDownloadFileDir -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.FileDownloadManager +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import java.io.File @@ -90,8 +88,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(true).init() - initLayoutImmersionBar(binding.rootView) + binding.rootView.initImmersionBar(this, true, R.color.white) binding.titleInclude.titleView.visibility = View.GONE } @@ -108,22 +105,26 @@ val downloadPath = url!!.appendDownloadUrl(FileType.APK) Log.d(kTag, "downloadApk => $downloadPath") //开始下载 - downloadPath.downloadFile(createDownloadFileDir().toString(), object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() - } + FileDownloadManager.Builder() + .setDownloadFileSource(downloadPath) + .setFileSuffix("apk") + .setFileSaveDirectory(createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadEnd(file: File) { + progressDialog.dismiss() + progressDialog.progress = 0 + //安装APK + installApk(file) + } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } + override fun onFailure(throwable: Throwable) { - override fun onDownloadEnd(file: File?) { - progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK - installApk(file) - } - }) + } + + override fun onProgressChanged(progress: Int) { + progressDialog.progress = progress + } + }).build().start() } private fun installApk(apkPackage: File?) { diff --git a/app/src/main/java/com/casic/electric/detector/vm/TaskViewModel.kt b/app/src/main/java/com/casic/electric/detector/vm/TaskViewModel.kt index 476a5f0..4b0bed6 100644 --- a/app/src/main/java/com/casic/electric/detector/vm/TaskViewModel.kt +++ b/app/src/main/java/com/casic/electric/detector/vm/TaskViewModel.kt @@ -2,125 +2,156 @@ import androidx.lifecycle.MutableLiveData import com.casic.electric.detector.base.BaseApplication -import com.casic.electric.detector.extensions.convertChinese -import com.casic.electric.detector.extensions.separateResponseState -import com.casic.electric.detector.extensions.toErrorMessage +import com.casic.electric.detector.extensions.getResponseMessage +import com.casic.electric.detector.extensions.getResponseState import com.casic.electric.detector.model.MarkerFileModel import com.casic.electric.detector.retrofit.RetrofitServiceManager import com.casic.electric.detector.utils.LabelDataClass +import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.SmallLabelDataClass import com.google.gson.Gson +import com.google.gson.JsonParser import com.google.gson.reflect.TypeToken +import com.pengxh.kt.lite.base.BaseViewModel import com.pengxh.kt.lite.extensions.launch import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.SaveKeyValues class TaskViewModel : BaseViewModel() { private val gson by lazy { Gson() } val markerFileResult = MutableLiveData() -// val taskResult = MutableLiveData() + + // val taskResult = MutableLiveData() + val freeTaskResult = MutableLiveData() + val uploadTaskMarkerResult = MutableLiveData() + + fun createFreeTask(patrollerId: String, description: String) = launch({ + val response = RetrofitServiceManager.createFreeTask(patrollerId, description) + if (response.getResponseState()) { + val element = JsonParser.parseString(response) + val jsonObject = element.asJsonObject + freeTaskResult.value = jsonObject.get("taskId").asInt.toString() + } else { + response.getResponseMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) + + fun uploadTaskMarker(taskId: String, models: ArrayList) = launch({ + val response = RetrofitServiceManager.uploadTaskMarker(taskId, models) + if (response.getResponseState()) { + val element = JsonParser.parseString(response) + val jsonObject = element.asJsonObject + uploadTaskMarkerResult.value = jsonObject.get("success").asString + } else { + response.getResponseMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) fun getMarkerFile(userId: String, companyId: String) = launch({ val response = RetrofitServiceManager.getMarkerFile(userId, companyId) - if (response.separateResponseState()) { + if (response.getResponseState()) { markerFileResult.value = gson.fromJson( response, object : TypeToken() {}.type ) } else { - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { - it.convertChinese().show(BaseApplication.get()) + it.printStackTrace() }) -// fun getTask(userName: String) = launch({ -// val response = RetrofitServiceManager.getTask(userName) -// if (response.separateResponseState()) { + fun getTask(userName: String) = launch({ + val response = RetrofitServiceManager.getTask(userName) + if (response.getResponseState()) { // taskResult.value = gson.fromJson( // response, object : TypeToken() {}.type // ) -// } else { -// response.toErrorMessage().show(BaseApplication.get()) -// } -// }, { -// it.convertChinese().show(BaseApplication.get()) -// }) + } else { + response.getResponseMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) fun installLabel(labelData: LabelDataClass) = launch({ loadState.value = LoadState.Loading val response = RetrofitServiceManager.installLabel(labelData) - if (response.separateResponseState()) { + if (response.getResponseState()) { loadState.value = LoadState.Success } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { + it.printStackTrace() loadState.value = LoadState.Fail - it.convertChinese().show(BaseApplication.get()) }) fun installSmallLabel(labelData: SmallLabelDataClass) = launch({ loadState.value = LoadState.Loading val response = RetrofitServiceManager.installSmallLabel(labelData) - if (response.separateResponseState()) { + if (response.getResponseState()) { loadState.value = LoadState.Success } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { + it.printStackTrace() loadState.value = LoadState.Fail - it.convertChinese().show(BaseApplication.get()) }) -// fun uploadTask(userId: String, taskId: String?, state: String) = launch({ -// loadState.value = LoadState.Loading -// val response = RetrofitServiceManager.uploadTask(userId, taskId, state) -// if (response.separateResponseState()) { -// loadState.value = LoadState.Success -// if (state == "2") { -// "工单${taskId}已提交!".show(BaseApplication.get()) -// //删除本地数据库 + fun uploadTask(userId: String, taskId: String?, state: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.uploadTask(userId, taskId, state) + if (response.getResponseState()) { + loadState.value = LoadState.Success + if (state == "2") { + "工单${taskId}已提交!".show(BaseApplication.get()) + //删除本地数据库 // DataBaseManager.get.deleteTaskById(taskId) -// SaveKeyValues.putValue(LocaleConstant.TASK_ID, "") -// } -// } else { -// loadState.value = LoadState.Fail -// response.toErrorMessage().show(BaseApplication.get()) -// } -// }, { -// loadState.value = LoadState.Fail -// it.convertChinese().show(BaseApplication.get()) -// }) + SaveKeyValues.putValue(LocaleConstant.TASK_ID, "") + } + } else { + loadState.value = LoadState.Fail + response.getResponseMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + loadState.value = LoadState.Fail + }) fun uploadEvent(taskId: String, event: String, realPaths: ArrayList) = launch({ loadState.value = LoadState.Loading val response = RetrofitServiceManager.uploadEvent(taskId, event, realPaths) - if (response.separateResponseState()) { + if (response.getResponseState()) { loadState.value = LoadState.Success } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { + it.printStackTrace() loadState.value = LoadState.Fail - it.convertChinese().show(BaseApplication.get()) }) - fun uploadMarker(userName: String, taskDetailId: String) = launch({ + fun uploadMarker(taskDetailId: String) = launch({ loadState.value = LoadState.Loading - val response = RetrofitServiceManager.uploadMarker(userName, taskDetailId) - if (response.separateResponseState()) { + val response = RetrofitServiceManager.uploadMarker(taskDetailId) + if (response.getResponseState()) { loadState.value = LoadState.Success } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { + it.printStackTrace() loadState.value = LoadState.Fail - it.convertChinese().show(BaseApplication.get()) }) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/vm/UserViewModel.kt b/app/src/main/java/com/casic/electric/detector/vm/UserViewModel.kt index e4a7b4e..ee6099b 100644 --- a/app/src/main/java/com/casic/electric/detector/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/electric/detector/vm/UserViewModel.kt @@ -2,17 +2,17 @@ import androidx.lifecycle.MutableLiveData import com.casic.electric.detector.base.BaseApplication -import com.casic.electric.detector.extensions.separateResponseState -import com.casic.electric.detector.extensions.toErrorMessage +import com.casic.electric.detector.extensions.getResponseMessage +import com.casic.electric.detector.extensions.getResponseState import com.casic.electric.detector.model.LoginResultModel import com.casic.electric.detector.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +import com.pengxh.kt.lite.base.BaseViewModel import com.pengxh.kt.lite.extensions.isNetworkConnected import com.pengxh.kt.lite.extensions.launch import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState /** * 用户相关 VM @@ -25,14 +25,14 @@ fun login(account: String, password: String) = launch({ loadState.value = LoadState.Loading val response = RetrofitServiceManager.login(account, password) - if (response.separateResponseState()) { + if (response.getResponseState()) { loadState.value = LoadState.Success loginResult.value = gson.fromJson( response, object : TypeToken() {}.type ) } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { loadState.value = LoadState.Fail diff --git a/app/src/main/java/com/casic/electric/detector/vm/VersionViewModel.kt b/app/src/main/java/com/casic/electric/detector/vm/VersionViewModel.kt index 6caf065..b488b5b 100644 --- a/app/src/main/java/com/casic/electric/detector/vm/VersionViewModel.kt +++ b/app/src/main/java/com/casic/electric/detector/vm/VersionViewModel.kt @@ -7,10 +7,10 @@ import com.casic.electric.detector.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +import com.pengxh.kt.lite.base.BaseViewModel import com.pengxh.kt.lite.extensions.launch import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class VersionViewModel : BaseViewModel() { private val gson by lazy { Gson() } diff --git a/app/src/main/res/layout/activity_big_image.xml b/app/src/main/res/layout/activity_big_image.xml index 9d060f4..228c2c4 100644 --- a/app/src/main/res/layout/activity_big_image.xml +++ b/app/src/main/res/layout/activity_big_image.xml @@ -1,5 +1,6 @@ + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt b/app/src/main/java/com/casic/electric/detector/extensions/Context.kt deleted file mode 100644 index fcf36a7..0000000 --- a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.casic.electric.detector.extensions - -import android.content.Context -import android.view.ViewGroup -import com.pengxh.kt.lite.extensions.getStatusBarHeight - -/** - * 设置沉浸式状态栏,兼容Android 11+ - * */ -fun Context.initLayoutImmersionBar(rootView: ViewGroup) { - rootView.setPadding(0, this.getStatusBarHeight(), 0, 0) - rootView.requestLayout() -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt index 6e08b27..e98408a 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt @@ -13,12 +13,4 @@ paint.color = color canvas.drawArc(rectF, 0f, 360f, true, paint) return bitmap -} - -fun Int.appendZero(): String { - return if (this < 10) { - "0$this" - } else { - this.toString() - } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/String.kt b/app/src/main/java/com/casic/electric/detector/extensions/String.kt index a0db0eb..838d3ad 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/String.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/String.kt @@ -3,14 +3,11 @@ import android.content.Context import android.widget.TextView import com.casic.electric.detector.callback.OnImageCompressListener -import com.casic.electric.detector.model.ErrorMessageModel import com.casic.electric.detector.utils.FileType import com.casic.electric.detector.utils.LocaleConstant -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken +import com.google.gson.JsonParser import com.pengxh.kt.lite.extensions.createCompressImageDir import com.pengxh.kt.lite.utils.SaveKeyValues -import org.json.JSONObject import top.zibin.luban.Luban import top.zibin.luban.OnCompressListener import java.io.File @@ -18,18 +15,22 @@ /** * String扩展方法 */ -fun String.separateResponseState(): Boolean { +fun String.getResponseState(): Boolean { if (this.isBlank()) { return false } - return JSONObject(this).getBoolean("success") + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("success").asBoolean } -fun String.toErrorMessage(): String { - val errorModel = Gson().fromJson( - this, object : TypeToken() {}.type - ) - return errorModel.message.toString() +fun String.getResponseMessage(): String { + if (this.isBlank()) { + return "" + } + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("message").asString } /** @@ -131,4 +132,9 @@ } else { "6" } +} + +fun String.isNumber(): Boolean { + val regex = Regex("[-+]?\\d+(\\.\\d+)?") + return this.matches(regex) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt new file mode 100644 index 0000000..8b78a3c --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt @@ -0,0 +1,31 @@ +package com.casic.electric.detector.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import androidx.fragment.app.Fragment +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} + +fun ViewGroup.initImmersionBar(fragment: Fragment, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(fragment) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(fragment.requireContext())) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = fragment.requireContext().getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt new file mode 100644 index 0000000..84c9cd9 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt @@ -0,0 +1,3 @@ +package com.casic.electric.detector.model + +data class CalculateResult(val angle: Int, val direction: String, val distance: Int) diff --git a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java b/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java deleted file mode 100644 index 1574393..0000000 --- a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.casic.electric.detector.model; - -public class ErrorMessageModel { - private int code; - private String data; - private String exceptionClazz; - private String message; - private boolean isSuccess; - - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public String getExceptionClazz() { - return exceptionClazz; - } - - public void setExceptionClazz(String exceptionClazz) { - this.exceptionClazz = exceptionClazz; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public boolean isSuccess() { - return isSuccess; - } - - public void setSuccess(boolean success) { - isSuccess = success; - } -} diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt index 950fb91..f590226 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt @@ -90,10 +90,25 @@ /** * 上传工单中标识器信息 + * info中的主键 */ @GET("/ems/rs/task/update-task-mark") suspend fun uploadMarker( - @Query("userName") userId: String, - @Query("taskDetailId") taskId: String, + @Query("taskDetailId") taskId: String ): String + + /** + * 新建自由巡检任务 + * */ + @GET("ems/rs/task/addAppTask") + suspend fun createFreeTask( + @Query("patrollerId") patrollerId: String, + @Query("description") description: String + ): String + + /** + * 上传自由巡检过程中发现的标识器 + * */ + @POST("ems/event/uploadAppMarker.do") + suspend fun uploadTaskMarker(@Body requestBody: RequestBody): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt index 6834fc5..7836b28 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt @@ -1,5 +1,6 @@ package com.casic.electric.detector.retrofit +import com.casic.electric.detector.extensions.reformat import com.casic.electric.detector.utils.LabelDataClass import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.SmallLabelDataClass @@ -15,43 +16,32 @@ object RetrofitServiceManager { + private fun createApi(): RetrofitService { + val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String + val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String + val httpConfig = "http://${serverIp}:${serverPort}" + return RetrofitFactory.createRetrofit(httpConfig) + } + /** * 登录 */ suspend fun login(account: String, password: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.login(account, password) + return createApi().login(account, password) } /** * 更新版本 * */ suspend fun getApplicationVersion(): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getApplicationVersion() + return createApi().getApplicationVersion() } /** * 获取标识器信息文件 */ suspend fun getMarkerFile(userId: String, companyId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getMarkerFile(userId, companyId) + return createApi().getMarkerFile(userId, companyId) } /** @@ -64,39 +54,21 @@ "application/json;charset=UTF-8".toMediaType() ) - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getLabelPicture(requestBody) + return createApi().getLabelPicture(requestBody) } /** * 获取巡检工单 */ suspend fun getTask(userName: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getTask(userName) + return createApi().getTask(userName) } /** * 提交工单 */ suspend fun uploadTask(userId: String, taskId: String?, state: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadTask(userId, taskId.toString(), state) + return createApi().uploadTask(userId, taskId.toString(), state) } /** @@ -164,27 +136,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installLabel(res, multiParts[0], multiParts[1], null) + createApi().installLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installLabel(res, multiParts[0], null, null) + createApi().installLabel(res, multiParts[0], null, null) } else -> { - api.installLabel(res, null, null, null) + createApi().installLabel(res, null, null, null) } } } @@ -230,27 +196,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], null) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installSmallLabel(res, multiParts[0], null, null) + createApi().installSmallLabel(res, multiParts[0], null, null) } else -> { - api.installSmallLabel(res, null, null, null) + createApi().installSmallLabel(res, null, null, null) } } } @@ -279,27 +239,23 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2]) + createApi().uploadEvent( + taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2] + ) } 2 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) } 1 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) } else -> { - api.uploadEvent(taskIdMap, eventMap, null, null, null) + createApi().uploadEvent(taskIdMap, eventMap, null, null, null) } } } @@ -307,13 +263,27 @@ /** * 上传工单中标识器信息 */ - suspend fun uploadMarker(userName: String, taskDetailId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadMarker(userName, taskDetailId) + suspend fun uploadMarker(taskDetailId: String): String { + return createApi().uploadMarker(taskDetailId) + } + + /** + * 上传工单中标识器信息 + */ + suspend fun createFreeTask(patrollerId: String, description: String): String { + return createApi().createFreeTask(patrollerId, description) + } + + /** + * 上传自由巡检过程中发现的标识器 + */ + suspend fun uploadTaskMarker(taskId: String, models: ArrayList): String { + val param = JsonObject() + param.addProperty("taskId", taskId) + param.addProperty("ids", models.reformat()) + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return createApi().uploadTaskMarker(requestBody) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java index 4aba809..45d5a2f 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java +++ b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java @@ -1,8 +1,10 @@ package com.casic.electric.detector.utils; -public class GpioManager { +import android.util.Log; +public class GpioManager { + private static final String TAG = "GpioManager"; private static final int MT6761 = 0; private int selected; private final MT6761Gpio mt6761; @@ -38,6 +40,7 @@ * 璁剧疆GPIO杈撳嚭楂� * *********************************************************************/ public void setGpioHigh(String gpio) { + Log.d(TAG, "setGpioHigh: 调高电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioHigh(); @@ -48,6 +51,7 @@ * 璁剧疆GPIO杈撳嚭浣� * *********************************************************************/ public void setGpioLow(String gpio) { + Log.d(TAG, "setGpioLow: 调低电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioLow(); diff --git a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt deleted file mode 100644 index c589c4b..0000000 --- a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.electric.detector.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt index 4de12f2..9356f9a 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt @@ -13,7 +13,7 @@ ) const val PERMISSIONS_CODE = 999 - const val RADIUS_SIZE = 100f //相距多少米才聚合,单位:米 + const val RADIUS_SIZE = 100 //相距多少米才聚合,单位:米 const val AUTO_SAVE = "AUTO_SAVE" const val USER_ACCOUNT = "USER_ACCOUNT" @@ -28,10 +28,21 @@ const val APP_AUTHORITY = "com.casic.electric.detector.fileprovider" val POPUP_TITLES = arrayOf("更新数据", "下载工单", "关于软件", "事件上报", "标识器补全") - var CONDITION_ARRAY = arrayOf("种类", "编号", "名称", "所属区域", "所属道路", "运检单位", "责任人", "建设时间", "标识器ID") + var CONDITION_ARRAY = arrayOf( + "种类", + "编号", + "名称", + "所属区域", + "所属道路", + "运检单位", + "责任人", + "建设时间", + "标识器ID" + ) var CONTENT_ARRAY = arrayOf("电缆井", "电缆通道", "配电房", "开关站", "台区", "杆塔") var OBJECT_MODE_ARRAY = arrayOf("直线井", "转弯井", "丁字井", "十字井", "其他") - var WELL_COVER_MATERIAL_ARRAY_1 = arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") + var WELL_COVER_MATERIAL_ARRAY_1 = + arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") var WELL_COVER_MATERIAL_ARRAY_2 = arrayOf("水泥杆", "钢管杆", "铁塔", "其他") var CABINET_TYPE_ARRAY = arrayOf("无", "SM6", "SAFE", "RM6", "XGN15", "固体柜") var PIPE_MATERIAL_ARRAY = arrayOf("无", "PVC管", "波纹管", "镀锌钢管") @@ -42,7 +53,16 @@ var CROSS_PIPE_STATE_ARRAY = booleanArrayOf(false, false, false, false, false, false, false) var POINT_TYPE_ARRAY = arrayOf("管线", "管线附属物", "管线特征管点", "交叉穿越点") - var SPINNER_ARRAY = arrayOf("标识器ID", "所属区域", "所属线路", "所属道路", "权属单位", "安装部门", "安装时间", "备注") + var SPINNER_ARRAY = arrayOf( + "标识器ID", + "所属区域", + "所属线路", + "所属道路", + "权属单位", + "安装部门", + "安装时间", + "备注" + ) var DOWN_PIPE_TYPE_ARRAY = arrayOf("热力", "燃气", "供水", "电力", "通信") var BURY_METHOD_ARRAY = arrayOf("直埋", "圆管", "管块", "管沟", "架空") var COLOR_ARRAY = arrayOf("蓝色", "橙色", "红色", "黑色", "紫色", "黄色", "绿色") diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt index 4f0f2c7..61e55f6 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt @@ -14,14 +14,16 @@ import com.casic.electric.detector.callback.IAddressListener import com.casic.electric.detector.callback.ILocationListener -object LocationHub { - private const val kTag = "LocationHub" +class LocationHub constructor(context: Context) { - fun getCurrentLocation(context: Context, listener: ILocationListener) { - val locationClient = AMapLocationClient(context) + private val kTag = "LocationHub" + private val locationClient by lazy { AMapLocationClient(context) } + private val codeSearch by lazy { GeocodeSearch(context) } + + fun getCurrentLocation(isOnceLocation: Boolean, listener: ILocationListener) { val locationOption = AMapLocationClientOption() locationOption.locationMode = AMapLocationClientOption.AMapLocationMode.Hight_Accuracy - locationOption.isOnceLocation = true + locationOption.isOnceLocation = isOnceLocation locationClient.setLocationOption(locationOption) locationClient.setLocationListener { if (it.errorCode == 0) { @@ -36,9 +38,8 @@ locationClient.startLocation() } - fun antiCodingLocation(context: Context, location: Location, listener: IAddressListener) { + fun antiCodingLocation(location: Location, listener: IAddressListener) { try { - val codeSearch = GeocodeSearch(context) // 第一个参数表示一个LatLonPoint,第二参数表示范围多少米,第三个参数表示是火系坐标系还是GPS原生坐标系 val query = RegeocodeQuery( LatLonPoint(location.latitude, location.longitude), 10f, GeocodeSearch.AMAP @@ -55,4 +56,8 @@ e.printStackTrace() } } + + fun stopLocation() { + locationClient.stopLocation() + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt b/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt index aa1bdeb..e3d3289 100644 --- a/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt @@ -1,7 +1,6 @@ package com.casic.electric.detector.view import android.content.Context -import android.graphics.Color import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -12,10 +11,10 @@ import com.bumptech.glide.Glide import com.casic.electric.detector.R import com.casic.electric.detector.databinding.ActivityBigImageBinding +import com.casic.electric.detector.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class BigImageActivity : KotlinBaseActivity() { @@ -24,20 +23,12 @@ } override fun setupTopBarLayout() { - ImmerseStatusBarUtil.setColor(this, Color.BLACK) + binding.rootView.initImmersionBar(this, false, R.color.black) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - val index: Int = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return @@ -62,6 +53,14 @@ }) } + override fun observeRequestState() { + + } + + override fun initEvent() { + + } + inner class BigImageAdapter( private val context: Context, private val data: ArrayList ) : PagerAdapter() { diff --git a/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt b/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt index d3a89ca..6510104 100644 --- a/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt @@ -29,15 +29,15 @@ import com.casic.electric.detector.extensions.* import com.casic.electric.detector.utils.* import com.casic.electric.detector.vm.TaskViewModel -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia import com.luck.picture.lib.interfaces.OnResultCallbackListener import com.pengxh.kt.lite.extensions.* +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -53,7 +53,8 @@ private val context: Context = this@InstallLabelActivity private val gpioManager by lazy { GpioManager() } private val calendar by lazy { Calendar.getInstance() } - private val realPaths: ArrayList = ArrayList() //真实图片路径 + private val locationHub by lazy { LocationHub(this) } + private val realPaths = ArrayList() //真实图片路径 private var soundResId = 0 private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var soundPool: SoundPool @@ -67,12 +68,6 @@ override fun setupTopBarLayout() { binding.titleInclude.titleView.text = "安装新标识器" binding.titleInclude.titleView.setTextColor(R.color.themeColor.convertColor(this)) - - ImmersionBar.with(this) - .statusBarDarkFont(true) - .statusBarColor(R.color.mainBackground) - .init() - initLayoutImmersionBar(binding.rootView) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -126,7 +121,7 @@ binding.markerAttrInclude.remarkView3.setText("remarkView3".getDefaultValue()) //初始化图片九宫格 - imageAdapter = EditableImageAdapter(this, 3, 3f) + imageAdapter = EditableImageAdapter(this, 3, 3) binding.cameraInclude.addImageRecyclerView.adapter = imageAdapter taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] @@ -332,7 +327,7 @@ binding.markerAttrInclude.installTimeView.text = System.currentTimeMillis().timestampToCompleteDate() - LocationHub.getCurrentLocation(this, object : ILocationListener { + locationHub.getCurrentLocation(true, object : ILocationListener { override fun onAMapLocationGet(location: AMapLocation?) { if (location != null) { binding.markerAttrInclude.lngView.text = location.longitude.toString() @@ -518,8 +513,8 @@ weakReferenceHandler.postDelayed({ try { // 发送读标识器或搜索信号 - outputStream?.write("2".toByteArray()) - outputStream?.flush() + out.write("2".toByteArray()) + out.flush() } catch (e: IOException) { e.printStackTrace() } @@ -527,7 +522,7 @@ } } - override fun onDataReceived(buffer: ByteArray?, size: Int) { + override fun onDataReceived(buffer: ByteArray) { Log.d(kTag, "onDataReceived => " + buffer.contentToString()) if (buffer != null) { val message = weakReferenceHandler.obtainMessage() diff --git a/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt b/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt index 5bc2ac8..286bf4a 100644 --- a/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt @@ -24,7 +24,6 @@ import com.casic.electric.detector.extensions.* import com.casic.electric.detector.utils.* import com.casic.electric.detector.vm.TaskViewModel -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -33,9 +32,10 @@ import com.pengxh.kt.lite.extensions.isNetworkConnected import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -65,12 +65,6 @@ override fun setupTopBarLayout() { binding.titleInclude.titleView.text = "安装新电子标签" binding.titleInclude.titleView.setTextColor(R.color.themeColor.convertColor(this)) - - ImmersionBar.with(this) - .statusBarDarkFont(true) - .statusBarColor(R.color.mainBackground) - .init() - initLayoutImmersionBar(binding.rootView) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -103,7 +97,7 @@ binding.objectAttrInclude.objectRemarkView3.setText("objectRemarkView3".getDefaultValue()) //初始化图片九宫格 - imageAdapter = EditableImageAdapter(this, 3, 3f) + imageAdapter = EditableImageAdapter(this, 3, 3) binding.cameraInclude.addImageRecyclerView.adapter = imageAdapter taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] @@ -308,8 +302,8 @@ weakReferenceHandler.postDelayed({ try { // 发送读标识器或搜索信号 - outputStream?.write("2".toByteArray()) - outputStream?.flush() + out.write("2".toByteArray()) + out.flush() } catch (e: IOException) { e.printStackTrace() } @@ -317,7 +311,7 @@ } } - override fun onDataReceived(buffer: ByteArray?, size: Int) { + override fun onDataReceived(buffer: ByteArray) { if (buffer != null) { val message = weakReferenceHandler.obtainMessage() message.what = 2023081702 diff --git a/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt b/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt index 44d56ef..9c98b5f 100644 --- a/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt @@ -1,36 +1,29 @@ package com.casic.electric.detector.view import android.os.Bundle -import android.util.Log import androidx.lifecycle.ViewModelProvider import com.amap.api.navi.NaviSetting import com.casic.electric.detector.databinding.ActivityLoginBinding -import com.casic.electric.detector.extensions.initLayoutImmersionBar -import com.casic.electric.detector.utils.GpioManager -import com.casic.electric.detector.utils.LoadingDialogHub import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.vm.UserViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.getScreenHeight -import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog class LoginActivity : KotlinBaseActivity() { private val kTag = "LoginActivity" private lateinit var userViewModel: UserViewModel - private val gpioManager by lazy { GpioManager() } override fun initViewBinding(): ActivityLoginBinding { return ActivityLoginBinding.inflate(layoutInflater) } override fun initOnCreate(savedInstanceState: Bundle?) { - gpioManager.setGpioLow("18") //先把导航隐私政策声明,后面导航会用到 NaviSetting.updatePrivacyShow(this, true, true) NaviSetting.updatePrivacyAgree(this, true) @@ -60,11 +53,8 @@ val serversIp = binding.serversIpView.text.toString() val serversPort = binding.serversPortView.text.toString() if (account.isBlank() || password.isBlank() || serversIp.isBlank() || serversPort.isBlank()) { - AlertMessageDialog.Builder() - .setContext(this) - .setTitle("账号登录") - .setMessage("信息不能为空哦!") - .setPositiveButton("知道了") + AlertMessageDialog.Builder().setContext(this).setTitle("账号登录") + .setMessage("信息不能为空哦!").setPositiveButton("知道了") .setOnDialogButtonClickListener(object : AlertMessageDialog.OnDialogButtonClickListener { override fun onConfirmClick() { @@ -102,9 +92,6 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(true).init() - initLayoutImmersionBar(binding.rootView) - - Log.d(kTag, "setupTopBarLayout => [${getScreenWidth()}, ${getScreenHeight()}]") } override fun onResume() { diff --git a/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt b/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt index 36a8d55..a0a4aac 100644 --- a/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt @@ -1,15 +1,21 @@ package com.casic.electric.detector.view +import android.annotation.SuppressLint import android.app.AlertDialog +import android.app.Dialog import android.content.Context -import android.content.Intent import android.graphics.Color import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable +import android.media.AudioAttributes +import android.media.SoundPool import android.os.Bundle -import android.os.PowerManager -import android.provider.Settings +import android.os.CountDownTimer +import android.util.Log import android.view.KeyEvent +import android.view.View +import android.view.animation.Animation +import android.view.animation.RotateAnimation import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import com.amap.api.location.AMapLocation @@ -21,6 +27,8 @@ import com.amap.api.maps.model.LatLngBounds import com.amap.api.maps.model.MyLocationStyle import com.casic.electric.detector.R +import com.casic.electric.detector.adapter.EditableImageAdapter +import com.casic.electric.detector.base.SerialPortActivity import com.casic.electric.detector.bean.LabelBean import com.casic.electric.detector.bean.SmallLabelBean import com.casic.electric.detector.bean.TaskBean @@ -29,83 +37,109 @@ import com.casic.electric.detector.cluster.ClusterOverlay import com.casic.electric.detector.cluster.RegionItem import com.casic.electric.detector.databinding.ActivityMainBinding +import com.casic.electric.detector.databinding.DialogInstallMarkerBinding +import com.casic.electric.detector.databinding.DialogInstallSmallMarkerBinding +import com.casic.electric.detector.databinding.DialogSearchMarkerBinding import com.casic.electric.detector.extensions.appendExcelDownloadUrl import com.casic.electric.detector.extensions.drawCircle -import com.casic.electric.detector.extensions.initLayoutImmersionBar +import com.casic.electric.detector.extensions.hexToString +import com.casic.electric.detector.extensions.initImmersionBar +import com.casic.electric.detector.extensions.isNumber +import com.casic.electric.detector.extensions.toHex import com.casic.electric.detector.utils.DataBaseManager import com.casic.electric.detector.utils.ExcelHub -import com.casic.electric.detector.utils.LoadingDialogHub +import com.casic.electric.detector.utils.GpioManager import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.LocationHub import com.casic.electric.detector.utils.RouteOnMap import com.casic.electric.detector.vm.TaskViewModel import com.casic.electric.detector.widgets.QueryMarkerDialog import com.casic.electric.detector.widgets.SamplePopupWindow -import com.gyf.immersionbar.ImmersionBar -import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.callback.OnDownloadListener +import com.google.gson.Gson +import com.pengxh.kt.lite.extensions.binding import com.pengxh.kt.lite.extensions.createDownloadFileDir -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.dp2px +import com.pengxh.kt.lite.extensions.initDialogLayoutParams import com.pengxh.kt.lite.extensions.isNetworkConnected import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.toJson +import com.pengxh.kt.lite.utils.FileDownloadManager +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog +import com.pengxh.kt.lite.widget.dialog.AlertInputDialog +import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File +import java.text.DecimalFormat +import java.util.Calendar +import java.util.Timer +import java.util.TimerTask -class MainActivity : KotlinBaseActivity() { +@SuppressLint("all") +class MainActivity : SerialPortActivity() { private val kTag = "MainActivity" - private val context: Context = this@MainActivity + private val context = this@MainActivity + private val gpioManager by lazy { GpioManager() } private val samplePopupWindow by lazy { SamplePopupWindow(this) } + private val gson by lazy { Gson() } + private val locationHub by lazy { LocationHub(this) } + private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } + private val backDrawables by lazy { HashMap() } + private val installMarkerDialog by lazy { InstallMarkerDialog(this) } + private val installSmallMarkerDialog by lazy { InstallSmallMarkerDialog(this) } + private val searchDialog by lazy { SearchMarkerDialog(this) } private var clickTime: Long = 0 - private lateinit var wakeLock: PowerManager.WakeLock - private lateinit var aMap: AMap - private lateinit var taskViewModel: TaskViewModel - private lateinit var taskBean: TaskBean - private var latitude: Double = 0.0 - private var longitude: Double = 0.0 private var labels = ArrayList() private var smallLabels = ArrayList() private var clusterOverlay: ClusterOverlay? = null - private val backDrawables = HashMap() - private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } + private var latitude: Double = 0.0 + private var longitude: Double = 0.0 + private var isFreeTask = false + private var ids = ArrayList() + private var signalTask: TimerTask? = null + private var searchMarkerTimer: Timer? = null + private lateinit var aMap: AMap + private lateinit var taskBean: TaskBean + private lateinit var taskId: String + + /***inner class 需要用到*****start*/ + private val taskViewModel by lazy { ViewModelProvider(this)[TaskViewModel::class.java] } + 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 var soundResourceId = 0 + private var slowSoundResourceId = 0 + private var fastSoundResourceId = 0 + + /***inner class 需要用到*****end*/ override fun initViewBinding(): ActivityMainBinding { return ActivityMainBinding.inflate(layoutInflater) } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).statusBarColor(R.color.themeColor).init() - initLayoutImmersionBar(binding.rootView) - } - - override fun observeRequestState() { - + binding.rootView.initImmersionBar(this, false, R.color.themeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { - val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager - wakeLock = powerManager.run { - newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this@MainActivity.localClassName).apply { - acquire(60 * 60 * 1000L) - } - } + soundResourceId = soundPool.load(this, R.raw.ring3, 1) + slowSoundResourceId = soundPool.load(this, R.raw.ring4, 1) + fastSoundResourceId = soundPool.load(this, R.raw.ring2, 1) + //地图初始化 initMapConfig(savedInstanceState) samplePopupWindow.setPopupMenuItem(LocaleConstant.POPUP_TITLES) samplePopupWindow.setBackgroundDrawable(null) - taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] + //task网络请求监听 taskViewModel.markerFileResult.observe(this) { if (it.success == "true") { //清空之前的数据 @@ -122,11 +156,13 @@ val smallLabelDownloadUrl = urlArray[1].appendExcelDownloadUrl() //下载标识器 - labelDownloadUrl.downloadFile( - createDownloadFileDir().toString(), object : OnDownloadListener { - override fun onDownloadEnd(file: File?) { + FileDownloadManager.Builder().setDownloadFileSource(labelDownloadUrl) + .setFileSuffix("xls").setFileSaveDirectory(createDownloadFileDir()) + .setOnFileDownloadListener(object : + FileDownloadManager.OnFileDownloadListener { + override fun onDownloadEnd(file: File) { lifecycleScope.launch { - labels = ExcelHub.readLabel(file?.absolutePath) + labels = ExcelHub.readLabel(file.absolutePath) withContext(Dispatchers.IO) { labels.forEach { label -> DataBaseManager.get.insertLabel(label) @@ -137,21 +173,23 @@ } } - override fun onDownloadStart(totalBytes: Long) { + override fun onFailure(throwable: Throwable) { } - override fun onProgressChanged(currentBytes: Long) { + override fun onProgressChanged(progress: Int) { } - }) + }).build().start() //下载附属标识器 - smallLabelDownloadUrl.downloadFile( - createDownloadFileDir().toString(), object : OnDownloadListener { - override fun onDownloadEnd(file: File?) { + FileDownloadManager.Builder().setDownloadFileSource(smallLabelDownloadUrl) + .setFileSuffix("xls").setFileSaveDirectory(createDownloadFileDir()) + .setOnFileDownloadListener(object : + FileDownloadManager.OnFileDownloadListener { + override fun onDownloadEnd(file: File) { lifecycleScope.launch { - smallLabels = ExcelHub.readSmallLabel(file?.absolutePath) + smallLabels = ExcelHub.readSmallLabel(file.absolutePath) withContext(Dispatchers.IO) { smallLabels.forEach { label -> DataBaseManager.get.insertSmallLabel(label) @@ -160,14 +198,14 @@ } } - override fun onDownloadStart(totalBytes: Long) { + override fun onFailure(throwable: Throwable) { } - override fun onProgressChanged(currentBytes: Long) { + override fun onProgressChanged(progress: Int) { } - }) + }).build().start() } } } @@ -175,11 +213,8 @@ // if (it.success == "true") { // //清空之前的数据 // DataBaseManager.get.clearTasks() -// AlertMessageDialog.Builder() -// .setContext(this) -// .setTitle("温馨提示") -// .setMessage("您有${it.message.size}个新任务!") -// .setPositiveButton("知道了") +// AlertMessageDialog.Builder().setContext(this).setTitle("温馨提示") +// .setMessage("您有${it.message.size}个新任务!").setPositiveButton("知道了") // .setOnDialogButtonClickListener(object : // AlertMessageDialog.OnDialogButtonClickListener { // override fun onConfirmClick() { @@ -188,19 +223,24 @@ // }).build().show() // } // } + taskViewModel.freeTaskResult.observe(this) { taskId = it } + taskViewModel.uploadTaskMarkerResult.observe(this) { + "自由巡检任务已完成".show(this) + ids.clear() + } } override fun initEvent() { binding.rightImageView.setOnClickListener { - CoroutineScope(Dispatchers.Main).launch { + lifecycleScope.launch(Dispatchers.Main) { val labels = withContext(Dispatchers.IO) { DataBaseManager.get.queryLabelById("0") } if (labels.isNotEmpty()) { samplePopupWindow.setShowPosition(4) } - val x = binding.rightImageView.width - samplePopupWindow.width - 1f.dp2px(context) - samplePopupWindow.showAsDropDown(binding.rightImageView, x, 1f.dp2px(context)) + val x = binding.rightImageView.width - samplePopupWindow.width - 1.dp2px(context) + samplePopupWindow.showAsDropDown(binding.rightImageView, x, 1.dp2px(context)) } } @@ -219,35 +259,33 @@ //安装。上传,然后存入本地库 binding.installButton.setOnClickListener { - AlertControlDialog.Builder() - .setContext(context) - .setTitle("提示") - .setMessage("请选择安装对象") - .setPositiveButton("标识器") - .setNegativeButton("电子标签") - .setOnDialogButtonClickListener(object : + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("请选择安装对象").setPositiveButton("标识器") + .setNegativeButton("电子标签").setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { //标识器 - navigatePageTo() + /** + * 改为Dialog方式,避免频繁打开/关闭串口 + * */ + installMarkerDialog.show() } override fun onCancelClick() { //电子标签 - navigatePageTo() + /** + * 改为Dialog方式,避免频繁打开/关闭串口 + * */ + installSmallMarkerDialog.show() } }).build().show() } //查看 binding.viewButton.setOnClickListener { - QueryMarkerDialog.Builder() - .setContext(this) - .setTitle("查看标识器") - .setConditionArray(LocaleConstant.CONDITION_ARRAY) - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : + QueryMarkerDialog.Builder().setContext(this).setTitle("查看标识器") + .setConditionArray(LocaleConstant.CONDITION_ARRAY).setNegativeButton("取消") + .setPositiveButton("确定").setOnDialogButtonClickListener(object : QueryMarkerDialog.OnDialogButtonClickListener { override fun onConfirmClick( selectedCondition: String, vararg contentValue: String @@ -310,30 +348,25 @@ // arrayList.add("任务${index + 1}:${taskBean.taskId},${taskBean.desc}") // } // -// BottomActionSheet.Builder() -// .setContext(this) -// .setItemTextColor(Color.BLUE) +// BottomActionSheet.Builder().setContext(this).setItemTextColor(Color.BLUE) // .setActionItemTitle(arrayList) // .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { // override fun onActionItemClick(position: Int) { // val taskBean = task[position] // SaveKeyValues.putValue(LocaleConstant.TASK_ID, taskBean.taskId) -// AlertControlDialog.Builder() -// .setContext(context) -// .setTitle("提示") -// .setMessage("请选择操作方式") -// .setPositiveButton("执行工单") +// AlertControlDialog.Builder().setContext(context).setTitle("提示") +// .setMessage("请选择操作方式").setPositiveButton("执行工单") // .setNegativeButton("提交工单") // .setOnDialogButtonClickListener(object : // AlertControlDialog.OnDialogButtonClickListener { // override fun onConfirmClick() { // detectRedrawGraphic(taskBean.taskId) +// +// val latLng = LatLng( +// taskBean.lat.toDouble(), taskBean.lng.toDouble() +// ) // aMap.moveCamera( -// CameraUpdateFactory.newLatLngZoom( -// LatLng( -// taskBean.lat.toDouble(), taskBean.lng.toDouble() -// ), 15f -// ) +// CameraUpdateFactory.newLatLngZoom(latLng, 16f) // ) // uploadTask(taskBean.taskId, "1") // } @@ -345,15 +378,12 @@ // } // }).build().show() // } else { -// AlertMessageDialog.Builder() -// .setContext(this) -// .setTitle("温馨提示") -// .setMessage("现有任务已完成,请点击右上角菜单按钮下载新工单!") -// .setPositiveButton("知道了") -// .setOnDialogButtonClickListener(object : +// AlertMessageDialog.Builder().setContext(this).setTitle("温馨提示") +// .setMessage("现有任务已完成,请点击右上角菜单下载新工单或者开始自由巡检") +// .setPositiveButton("知道了").setOnDialogButtonClickListener(object : // AlertMessageDialog.OnDialogButtonClickListener { // override fun onConfirmClick() { -// +// startFreeTask() // } // }).build().show() // } @@ -361,7 +391,118 @@ //探测 binding.detectionButton.setOnClickListener { -// navigatePageTo() + /** + * 改为Dialog方式,避免频繁打开/关闭串口 + * */ + searchDialog.show() + } + + //自由巡检 + binding.stopFreeTaskButton.setOnLongClickListener { + AlertMessageDialog.Builder().setContext(this).setTitle("温馨提示") + .setMessage("是否确定结束此次自由巡检任务?").setPositiveButton("是") + .setOnDialogButtonClickListener(object : + AlertMessageDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + isFreeTask = false + soundPool.autoPause() + + //降低串口电位 + gpioManager.setGpioLow("18") + + taskViewModel.uploadTaskMarker(taskId, ids) + binding.stopFreeTaskButton.visibility = View.GONE + } + }).build().show() + true + } + } + + private fun startFreeTask() { + AlertInputDialog.Builder().setContext(this).setTitle("新建自由巡检任务") + .setHintMessage("请输入自由巡检任务简要描述").setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : AlertInputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String + taskViewModel.createFreeTask(userId, value) + + //调高串口电位 + gpioManager.setGpioHigh("18") + + soundPool.play(soundResourceId, 1f, 1f, 0, -1, 1f) + isFreeTask = true + //自由巡检 + signalTask = object : TimerTask() { + override fun run() { + out.write('2'.code) + out.flush() + } + } + searchMarkerTimer = Timer() + searchMarkerTimer?.apply { + schedule(signalTask, 0, 100) + } + + binding.stopFreeTaskButton.visibility = View.VISIBLE + } + + override fun onCancelClick() {} + }).build().show() + } + + override fun onDataReceived(buffer: ByteArray) { + val hex = buffer.toHex() + Log.d(kTag, "$kTag => $hex") + if (searchDialog.isDetectMarker) { + searchDialog.bindingValue(hex) +// } else if (installMarkerDialog.isReadMarker) { +// val markerId = hex.take(20).hexToString() +// if (markerId.isNumber()) { +// installMarkerDialog.bindingValue(markerId) +// } +// } else if (installSmallMarkerDialog.isReadMarker) { +// val markerId = hex.take(20).hexToString() +// if (markerId.isNumber()) { +// installSmallMarkerDialog.bindingValue(markerId) +// } + } else if (isFreeTask) { + val markerId = hex.take(20).hexToString() + if (markerId.isNumber()) { + "标识器${markerId}已探测".show(this) + ids.add(markerId) + } + } + } + + override fun observeRequestState() { + taskViewModel.loadState.observe(this) { + when (it) { + LoadState.Loading -> { + if (installMarkerDialog.isInstallMarker || installSmallMarkerDialog.isInstallMarker) { + LoadingDialogHub.show(this, "标识器安装中,请稍后...") + } else if (searchDialog.isDetectMarker) { + searchDialog.taskBean?.apply { + "标识器${this.markerId}已探测!".show(context) +// DataBaseManager.get.updateTaskLabel(this) + } + } else { + LoadingDialogHub.show(this, "提交工单中,请稍后") + } + } + + else -> { + if (installMarkerDialog.isInstallMarker) { + installMarkerDialog.dismiss() + installMarkerDialog.isInstallMarker = false + } else if (installSmallMarkerDialog.isInstallMarker) { + installSmallMarkerDialog.dismiss() + installSmallMarkerDialog.isInstallMarker = false + } + LoadingDialogHub.dismiss() + } + } + detectRedrawGraphic(taskBean.taskId) } } @@ -375,6 +516,7 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜 //显示定位小蓝点 val locationStyle = MyLocationStyle() locationStyle.interval(2000) @@ -387,7 +529,7 @@ longitude = it.longitude latitude = it.latitude //经纬度逆编码 - LocationHub.antiCodingLocation(context, it) { address -> + locationHub.antiCodingLocation(it) { address -> binding.currentLocationView.text = address } } @@ -417,7 +559,7 @@ } private fun moveToCurrentLocation() { - LocationHub.getCurrentLocation(this, object : ILocationListener { + locationHub.getCurrentLocation(true, object : ILocationListener { override fun onAMapLocationGet(location: AMapLocation?) { if (location != null) { aMap.moveCamera( @@ -432,46 +574,35 @@ }) } - //更新数据 - private fun updateLabels() { - AlertControlDialog.Builder() - .setContext(this) - .setTitle("提示") - .setMessage("是否更新数据?") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onConfirmClick() { - if (isNetworkConnected()) { - val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") - val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") - - LoadingDialogHub.show(this@MainActivity, "获取标识器信息中,请稍后") - //TODO 设计如此,都传companyId - taskViewModel.getMarkerFile(companyId.toString(), companyId.toString()) - } else { - NoNetworkDialog.Builder() - .setContext(context) - .setOnDialogButtonClickListener(object : - NoNetworkDialog.OnDialogButtonClickListener { - override fun onButtonClick() { - val intent = Intent(Settings.ACTION_SETTINGS) - startActivity(intent) - } - }).build().show() - } - } - - override fun onCancelClick() { - - } - }).build().show() - } +// private fun saveTaskInformation(it: TaskModel) { +// val userName = SaveKeyValues.getValue(LocaleConstant.USER_NAME, "") as String +// if (it.message.size > 0) { +// it.message.forEach { messageModel -> +// val count = DataBaseManager.get.countTaskById(messageModel.id.toString()) +// if (count == 0) { +// messageModel.taskDetailInfos.forEach { info -> +// DataBaseManager.get.insertTaskInformation( +// userName, +// messageModel.description, +// info.taskId.toString(), +// info.id.toString(), +// info.markerId.toString(), +// info.markerIdReal.toString(), +// info.longitude.toString(), +// info.latitude.toString(), +// messageModel.status +// ) +// } +// } +// } +// "工单下载成功!".show(context) +// } +// } private fun showLabelsOnMap() { clusterOverlay?.onDestroy() val clusterItems = ArrayList() + labels.forEach { val latLng = LatLng(it.latitude.toDouble(), it.longitude.toDouble(), false) val regionItem = RegionItem(latLng, it.markerId.toString()) @@ -480,7 +611,7 @@ clusterOverlay = ClusterOverlay(context, aMap, clusterItems, regionRadius) clusterOverlay?.setClusterRender { clusterNum -> - val radius = 80f.dp2px(context) + val radius = 80.dp2px(context) if (clusterNum == 0) { var bitmapDrawable = backDrawables[0] if (bitmapDrawable == null) { @@ -546,9 +677,7 @@ val latLngBounds = builder.build() aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 0)) - BottomActionSheet.Builder() - .setContext(this) - .setItemTextColor(Color.BLUE) + BottomActionSheet.Builder().setContext(this).setItemTextColor(Color.BLUE) .setActionItemTitle(listOf("标识器信息", "附属电子标签信息", "到这里去")) .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { override fun onActionItemClick(position: Int) { @@ -578,12 +707,7 @@ showElectricMarkers(electricMarkers) } - 2 -> { - RouteOnMap.startNavigation( - context, item.tag, - LatLng(item.position.latitude, item.position.longitude) - ) - } + 2 -> RouteOnMap.startNavigation(context, item.tag, latLng) } } }).build().show() @@ -591,14 +715,74 @@ } private fun showElectricMarkers(markers: ArrayList) { - AlertDialog.Builder(context) - .setIcon(R.mipmap.ic_launcher) - .setTitle("电子标签列表") + AlertDialog.Builder(context).setIcon(R.mipmap.ic_launcher).setTitle("电子标签列表") .setSingleChoiceItems(markers.toTypedArray(), -1) { _, which -> navigatePageTo(markers[which]) }.show() } + private fun detectRedrawGraphic(taskId: String) { +// val tasks = DataBaseManager.get.queryTaskById(taskId) +// if (tasks.isNotEmpty()) { +// tasks.forEach { +// val latLng = LatLng(it.lat.toDouble(), it.lng.toDouble()) +// val otMarkerOptions = MarkerOptions() +// otMarkerOptions.position(latLng) +// otMarkerOptions.visible(true) // 设置可见 +// if (it.state == "未开始") { +// otMarkerOptions.icon( +// BitmapDescriptorFactory.fromBitmap( +// BitmapFactory.decodeResource(resources, R.mipmap.label_red1) +// ) +// ).period(99).title("工单标识器").snippet(it.markerId) +// } else { +// otMarkerOptions.icon( +// BitmapDescriptorFactory.fromBitmap( +// BitmapFactory.decodeResource(resources, R.mipmap.label_blue1) +// ) +// ).period(99).title("工单标识器").snippet(it.markerId) +// } +// aMap.addMarker(otMarkerOptions) +// } +// } + showLabelsOnMap() + } + + private fun uploadTask(taskId: String?, state: String) { + if (isNetworkConnected()) { + val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String + taskViewModel.uploadTask(userId, taskId, state) + } else { + "网络连接已断开,请检查".show(this) + } + } + + //更新数据 + private fun updateLabels() { + AlertControlDialog.Builder().setContext(this).setTitle("提示").setMessage("是否更新数据?") + .setNegativeButton("取消").setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + if (isNetworkConnected()) { + val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") + + LoadingDialogHub.show(this@MainActivity, "获取标识器信息中,请稍后") + /** + * 后台设计如此,都传companyId + * */ + taskViewModel.getMarkerFile(companyId.toString(), companyId.toString()) + } else { + "网络连接已断开,请检查".show(context) + } + } + + override fun onCancelClick() { + + } + }).build().show() + } + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { return if (keyCode == KeyEvent.KEYCODE_BACK) { if (System.currentTimeMillis() - clickTime > 2000) { @@ -643,8 +827,270 @@ } override fun onDestroy() { - wakeLock.release() super.onDestroy() binding.mapView.onDestroy() + signalTask?.cancel() + searchMarkerTimer?.cancel() + soundPool.release() + locationHub.stopLocation() + //降低串口电位 + gpioManager.setGpioLow("18") + } + + /**安装标识器对话框******************************************************************************/ + inner class InstallMarkerDialog(context: Context) : Dialog(context) { + + private val binding: DialogInstallMarkerBinding by binding() + private val calendar by lazy { Calendar.getInstance() } + private val realPaths = ArrayList() //真实图片路径 + private lateinit var imageAdapter: EditableImageAdapter + + var isReadMarker = false + var isInstallMarker = false + } + + /**安装小标签对话框******************************************************************************/ + inner class InstallSmallMarkerDialog(context: Context) : Dialog(context) { + + private val binding: DialogInstallSmallMarkerBinding by binding() + private val calendar by lazy { Calendar.getInstance() } + private val realPaths = ArrayList() //真实图片路径 + private lateinit var imageAdapter: EditableImageAdapter + + var isReadMarker = false + var isInstallMarker = false + } + + /**探测标识器对话框******************************************************************************/ + inner class SearchMarkerDialog(context: Context) : Dialog(context) { + + private val binding: DialogSearchMarkerBinding by binding() + private val decimal by lazy { DecimalFormat("0.0") } + private val degreeCache by lazy { HashMap() } + private var isPlaying = false + private var markerId = "" + private lateinit var searchMarkerTimer: Timer + private lateinit var signalTask: TimerTask + private lateinit var energyTask: TimerTask + private lateinit var countDownTimer: CountDownTimer + + var isDetectMarker = false + var taskBean: TaskBean? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.initDialogLayoutParams(1f) + binding.depthButton.setOnClickListener { + signalTask.cancel() + energyTask.cancel() + searchMarkerTimer.cancel() + + out.write('3'.code) +// val result = DataBaseManager.get.queryLabelById(markerId) +// if (result.isNotEmpty()) { +// val tag = when (result.first().identifierType) { +// "EM30" -> '7' +// "EM50" -> '8' +// "EM14" -> '9' +// else -> '1' +// } +// if (tag == '1') { +// "此标识器无法读取埋深!".show(context) +// } else { +// // 发送读取标识器埋设深度指令 +// LoadingDialogHub.show(this@MainActivity, "正在测距,请稍后...") +// out.write(tag.code) +// out.flush() +// countDownTimer = object : CountDownTimer(15 * 1000, 1000) { +// override fun onTick(millisUntilFinished: Long) { +// +// } +// +// override fun onFinish() { +// LoadingDialogHub.dismiss() +// "探测此标识器深度超时,请重试".show(context) +// initTimer() +// } +// } +// countDownTimer.start() +// } +// } else { +// "标识器未安装,安装成功后才可读取埋深!".show(context) +// } + } + + binding.markerInfoButton.setOnClickListener { + //查库 + val result = DataBaseManager.get.queryLabelById(markerId) + if (result.isNotEmpty()) { +// context.navigatePageTo(result.first().toJson()) + } else { +// context.navigatePageTo(markerId) + } + } + } + + override fun onStart() { + super.onStart() + //调高串口电位 + gpioManager.setGpioHigh("18") + + initTimer() + + isDetectMarker = true + + //角度 + degreeCache["lastDegree"] = 0f + } + + fun bindingValue(hex: String) { + if (hex.startsWith("4E")) { + try { + //4E转为String为N,代表能量值 + //用能量值转动表盘 + val energyResponse = hex.take(10).hexToString() + val energy = energyResponse.substring(1).toInt() + if (energy >= 4000) { + isPlaying = if (!isPlaying) { + soundPool.play(fastSoundResourceId, 1f, 1f, 0, 0, 1f) + true + } else { + soundPool.pause(fastSoundResourceId) + false + } + } else { + isPlaying = if (!isPlaying) { + soundPool.play(slowSoundResourceId, 1f, 1f, 0, 0, 1f) + true + } else { + soundPool.pause(slowSoundResourceId) + false + } + } + + binding.resultTextView.text = "信号能量值:${energyResponse}" + + //转换为转动的角度 + val degree = (energy.toFloat() / (50 * 100)) * 180 + binding.energyValueView.text = decimal.format(degree) + + degreeCache["lastDegree"]?.apply { + val animation = RotateAnimation( + this, degree, + Animation.RELATIVE_TO_SELF, 0.5f, + Animation.RELATIVE_TO_SELF, 0.5f + ) + animation.duration = 0 + animation.fillAfter = true + binding.needleView.startAnimation(animation) + } + + //保存旋转后的角度 + degreeCache["lastDegree"] = degree + + if (energy <= 700) {//18° + binding.energyTipsView.text = "标识器信号较弱,可能距离较远" + binding.energyTipsView.setTextColor(Color.parseColor("#8D1717")) + binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_red) + + binding.depthButton.isEnabled = false + binding.depthButton.setTextColor(Color.parseColor("#CCCCCC")) + binding.depthButton.setBackgroundResource(R.mipmap.left_button_disable) + binding.markerInfoButton.isEnabled = false + binding.markerInfoButton.setTextColor(Color.parseColor("#CCCCCC")) + binding.markerInfoButton.setBackgroundResource(R.mipmap.right_button_disable) + + binding.searchResultView.text = "未检测到标识器" + binding.searchResultView.setTextColor(Color.parseColor("#8D1717")) + binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_red) + } else if (energy >= 4100) {//148° + binding.energyTipsView.text = "标识器信号极强,可能在正下方" + binding.energyTipsView.setTextColor(Color.parseColor("#428d00")) + binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_green) + } else {//[18°,148°] + binding.energyTipsView.text = "已靠近标识器,请继续移动位置" + binding.energyTipsView.setTextColor(Color.parseColor("#8C5700")) + binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_yellow) + } + } catch (e: NumberFormatException) { + e.printStackTrace() + } + } else if (hex.startsWith("53")) { + LoadingDialogHub.dismiss() + countDownTimer.cancel() + try { + val depthResponse = hex.take(10).hexToString() + val depth = depthResponse.drop(2).toInt() + AlertMessageDialog.Builder().setContext(context).setTitle("温馨提示") + .setMessage("标识器埋深:${depth}厘米").setPositiveButton("知道了") + .setOnDialogButtonClickListener(object : + AlertMessageDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + initTimer() + } + }).build().show() + } catch (e: NumberFormatException) { + e.printStackTrace() + } + } else { + val id = hex.take(20).hexToString() + if (id.isNumber()) { + markerId = id + + binding.depthButton.isEnabled = true + binding.depthButton.setTextColor(Color.WHITE) + binding.depthButton.setBackgroundResource(R.mipmap.left_button_enable) + binding.markerInfoButton.isEnabled = true + binding.markerInfoButton.setTextColor(Color.WHITE) + binding.markerInfoButton.setBackgroundResource(R.mipmap.right_button_enable) + + binding.searchResultView.text = "已检测到标识器" + binding.searchResultView.setTextColor(Color.parseColor("#428d00")) + binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_green) + + //自动上传标识器 +// taskBean = DataBaseManager.get.queryTaskLabelByIdAndState(markerId, "未开始") +// taskBean?.apply { +// /** +// * 此taskCode是 [com.casic.detector.model.TaskModel.MessageModel.TaskDetailInfosModel] 里面的主键,也就是这个标签在数据库里面的主键 +// * */ +// taskViewModel.uploadMarker(taskCode) +// } + } + } + } + + private fun initTimer() { + searchMarkerTimer = Timer() + + signalTask = object : TimerTask() { + override fun run() { + out.write('2'.code) + out.flush() + } + } + + energyTask = object : TimerTask() { + override fun run() { + out.write('6'.code) + out.flush() + } + } + + //错开信号和能量定时器 + searchMarkerTimer.schedule(signalTask, 0, 201) + searchMarkerTimer.schedule(energyTask, 0, 251) + } + + override fun dismiss() { + signalTask.cancel() + energyTask.cancel() + searchMarkerTimer.cancel() + //降低串口电位 + gpioManager.setGpioLow("18") + isDetectMarker = false + soundPool.autoPause() + super.dismiss() + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt b/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt index 6a00429..cbd6137 100644 --- a/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt @@ -13,18 +13,16 @@ import com.casic.electric.detector.R import com.casic.electric.detector.databinding.ActivityVersionControlBinding import com.casic.electric.detector.extensions.appendDownloadUrl -import com.casic.electric.detector.extensions.initLayoutImmersionBar +import com.casic.electric.detector.extensions.initImmersionBar import com.casic.electric.detector.utils.FileType -import com.casic.electric.detector.utils.LoadingDialogHub import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.vm.VersionViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.createDownloadFileDir -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.FileDownloadManager +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import java.io.File @@ -90,8 +88,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(true).init() - initLayoutImmersionBar(binding.rootView) + binding.rootView.initImmersionBar(this, true, R.color.white) binding.titleInclude.titleView.visibility = View.GONE } @@ -108,22 +105,26 @@ val downloadPath = url!!.appendDownloadUrl(FileType.APK) Log.d(kTag, "downloadApk => $downloadPath") //开始下载 - downloadPath.downloadFile(createDownloadFileDir().toString(), object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() - } + FileDownloadManager.Builder() + .setDownloadFileSource(downloadPath) + .setFileSuffix("apk") + .setFileSaveDirectory(createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadEnd(file: File) { + progressDialog.dismiss() + progressDialog.progress = 0 + //安装APK + installApk(file) + } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } + override fun onFailure(throwable: Throwable) { - override fun onDownloadEnd(file: File?) { - progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK - installApk(file) - } - }) + } + + override fun onProgressChanged(progress: Int) { + progressDialog.progress = progress + } + }).build().start() } private fun installApk(apkPackage: File?) { diff --git a/app/src/main/java/com/casic/electric/detector/vm/TaskViewModel.kt b/app/src/main/java/com/casic/electric/detector/vm/TaskViewModel.kt index 476a5f0..4b0bed6 100644 --- a/app/src/main/java/com/casic/electric/detector/vm/TaskViewModel.kt +++ b/app/src/main/java/com/casic/electric/detector/vm/TaskViewModel.kt @@ -2,125 +2,156 @@ import androidx.lifecycle.MutableLiveData import com.casic.electric.detector.base.BaseApplication -import com.casic.electric.detector.extensions.convertChinese -import com.casic.electric.detector.extensions.separateResponseState -import com.casic.electric.detector.extensions.toErrorMessage +import com.casic.electric.detector.extensions.getResponseMessage +import com.casic.electric.detector.extensions.getResponseState import com.casic.electric.detector.model.MarkerFileModel import com.casic.electric.detector.retrofit.RetrofitServiceManager import com.casic.electric.detector.utils.LabelDataClass +import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.SmallLabelDataClass import com.google.gson.Gson +import com.google.gson.JsonParser import com.google.gson.reflect.TypeToken +import com.pengxh.kt.lite.base.BaseViewModel import com.pengxh.kt.lite.extensions.launch import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.SaveKeyValues class TaskViewModel : BaseViewModel() { private val gson by lazy { Gson() } val markerFileResult = MutableLiveData() -// val taskResult = MutableLiveData() + + // val taskResult = MutableLiveData() + val freeTaskResult = MutableLiveData() + val uploadTaskMarkerResult = MutableLiveData() + + fun createFreeTask(patrollerId: String, description: String) = launch({ + val response = RetrofitServiceManager.createFreeTask(patrollerId, description) + if (response.getResponseState()) { + val element = JsonParser.parseString(response) + val jsonObject = element.asJsonObject + freeTaskResult.value = jsonObject.get("taskId").asInt.toString() + } else { + response.getResponseMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) + + fun uploadTaskMarker(taskId: String, models: ArrayList) = launch({ + val response = RetrofitServiceManager.uploadTaskMarker(taskId, models) + if (response.getResponseState()) { + val element = JsonParser.parseString(response) + val jsonObject = element.asJsonObject + uploadTaskMarkerResult.value = jsonObject.get("success").asString + } else { + response.getResponseMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) fun getMarkerFile(userId: String, companyId: String) = launch({ val response = RetrofitServiceManager.getMarkerFile(userId, companyId) - if (response.separateResponseState()) { + if (response.getResponseState()) { markerFileResult.value = gson.fromJson( response, object : TypeToken() {}.type ) } else { - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { - it.convertChinese().show(BaseApplication.get()) + it.printStackTrace() }) -// fun getTask(userName: String) = launch({ -// val response = RetrofitServiceManager.getTask(userName) -// if (response.separateResponseState()) { + fun getTask(userName: String) = launch({ + val response = RetrofitServiceManager.getTask(userName) + if (response.getResponseState()) { // taskResult.value = gson.fromJson( // response, object : TypeToken() {}.type // ) -// } else { -// response.toErrorMessage().show(BaseApplication.get()) -// } -// }, { -// it.convertChinese().show(BaseApplication.get()) -// }) + } else { + response.getResponseMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) fun installLabel(labelData: LabelDataClass) = launch({ loadState.value = LoadState.Loading val response = RetrofitServiceManager.installLabel(labelData) - if (response.separateResponseState()) { + if (response.getResponseState()) { loadState.value = LoadState.Success } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { + it.printStackTrace() loadState.value = LoadState.Fail - it.convertChinese().show(BaseApplication.get()) }) fun installSmallLabel(labelData: SmallLabelDataClass) = launch({ loadState.value = LoadState.Loading val response = RetrofitServiceManager.installSmallLabel(labelData) - if (response.separateResponseState()) { + if (response.getResponseState()) { loadState.value = LoadState.Success } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { + it.printStackTrace() loadState.value = LoadState.Fail - it.convertChinese().show(BaseApplication.get()) }) -// fun uploadTask(userId: String, taskId: String?, state: String) = launch({ -// loadState.value = LoadState.Loading -// val response = RetrofitServiceManager.uploadTask(userId, taskId, state) -// if (response.separateResponseState()) { -// loadState.value = LoadState.Success -// if (state == "2") { -// "工单${taskId}已提交!".show(BaseApplication.get()) -// //删除本地数据库 + fun uploadTask(userId: String, taskId: String?, state: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.uploadTask(userId, taskId, state) + if (response.getResponseState()) { + loadState.value = LoadState.Success + if (state == "2") { + "工单${taskId}已提交!".show(BaseApplication.get()) + //删除本地数据库 // DataBaseManager.get.deleteTaskById(taskId) -// SaveKeyValues.putValue(LocaleConstant.TASK_ID, "") -// } -// } else { -// loadState.value = LoadState.Fail -// response.toErrorMessage().show(BaseApplication.get()) -// } -// }, { -// loadState.value = LoadState.Fail -// it.convertChinese().show(BaseApplication.get()) -// }) + SaveKeyValues.putValue(LocaleConstant.TASK_ID, "") + } + } else { + loadState.value = LoadState.Fail + response.getResponseMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + loadState.value = LoadState.Fail + }) fun uploadEvent(taskId: String, event: String, realPaths: ArrayList) = launch({ loadState.value = LoadState.Loading val response = RetrofitServiceManager.uploadEvent(taskId, event, realPaths) - if (response.separateResponseState()) { + if (response.getResponseState()) { loadState.value = LoadState.Success } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { + it.printStackTrace() loadState.value = LoadState.Fail - it.convertChinese().show(BaseApplication.get()) }) - fun uploadMarker(userName: String, taskDetailId: String) = launch({ + fun uploadMarker(taskDetailId: String) = launch({ loadState.value = LoadState.Loading - val response = RetrofitServiceManager.uploadMarker(userName, taskDetailId) - if (response.separateResponseState()) { + val response = RetrofitServiceManager.uploadMarker(taskDetailId) + if (response.getResponseState()) { loadState.value = LoadState.Success } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { + it.printStackTrace() loadState.value = LoadState.Fail - it.convertChinese().show(BaseApplication.get()) }) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/vm/UserViewModel.kt b/app/src/main/java/com/casic/electric/detector/vm/UserViewModel.kt index e4a7b4e..ee6099b 100644 --- a/app/src/main/java/com/casic/electric/detector/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/electric/detector/vm/UserViewModel.kt @@ -2,17 +2,17 @@ import androidx.lifecycle.MutableLiveData import com.casic.electric.detector.base.BaseApplication -import com.casic.electric.detector.extensions.separateResponseState -import com.casic.electric.detector.extensions.toErrorMessage +import com.casic.electric.detector.extensions.getResponseMessage +import com.casic.electric.detector.extensions.getResponseState import com.casic.electric.detector.model.LoginResultModel import com.casic.electric.detector.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +import com.pengxh.kt.lite.base.BaseViewModel import com.pengxh.kt.lite.extensions.isNetworkConnected import com.pengxh.kt.lite.extensions.launch import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState /** * 用户相关 VM @@ -25,14 +25,14 @@ fun login(account: String, password: String) = launch({ loadState.value = LoadState.Loading val response = RetrofitServiceManager.login(account, password) - if (response.separateResponseState()) { + if (response.getResponseState()) { loadState.value = LoadState.Success loginResult.value = gson.fromJson( response, object : TypeToken() {}.type ) } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { loadState.value = LoadState.Fail diff --git a/app/src/main/java/com/casic/electric/detector/vm/VersionViewModel.kt b/app/src/main/java/com/casic/electric/detector/vm/VersionViewModel.kt index 6caf065..b488b5b 100644 --- a/app/src/main/java/com/casic/electric/detector/vm/VersionViewModel.kt +++ b/app/src/main/java/com/casic/electric/detector/vm/VersionViewModel.kt @@ -7,10 +7,10 @@ import com.casic.electric.detector.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +import com.pengxh.kt.lite.base.BaseViewModel import com.pengxh.kt.lite.extensions.launch import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class VersionViewModel : BaseViewModel() { private val gson by lazy { Gson() } diff --git a/app/src/main/res/layout/activity_big_image.xml b/app/src/main/res/layout/activity_big_image.xml index 9d060f4..228c2c4 100644 --- a/app/src/main/res/layout/activity_big_image.xml +++ b/app/src/main/res/layout/activity_big_image.xml @@ -1,5 +1,6 @@ + + + android:value="d90fb9b5d8a4a139dec31e7ed6986147" /> () { private val layoutInflater by lazy { LayoutInflater.from(context) } diff --git a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt index 475a302..0dbff79 100644 --- a/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt +++ b/app/src/main/java/com/casic/electric/detector/base/BaseApplication.kt @@ -13,17 +13,19 @@ class BaseApplication : Application() { private val kTag = "BaseApplication" - private var serialPort: SerialPort? = null + private var serialPorts: ArrayList? = null @Throws(SecurityException::class, IOException::class, InvalidParameterException::class) - fun getSerialPort(): SerialPort? { - if (serialPort == null) { - /** - * Open the serial port - * */ - serialPort = SerialPort(File("/dev/ttysWK1"), 9600, 0) + fun getSerialPorts(): ArrayList? { + serialPorts = ArrayList() + /** + * Open the serial port + * */ + serialPorts?.apply { + add(SerialPort(File("/dev/ttysWK1"), 9600, 0)) + add(SerialPort(File("/dev/ttysWK2"), 9600, 0)) } - return serialPort + return serialPorts } companion object { @@ -48,9 +50,8 @@ } fun closeSerialPort() { - if (serialPort != null) { - serialPort?.close() - serialPort = null + serialPorts?.forEach { + it.close() } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt index ac05531..f6e6574 100644 --- a/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/base/SerialPortActivity.kt @@ -2,11 +2,14 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding -import com.casic.electric.detector.uart.SerialPort import com.pengxh.kt.lite.extensions.show +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.IOException -import java.io.InputStream import java.io.OutputStream import java.security.InvalidParameterException @@ -14,30 +17,8 @@ abstract class SerialPortActivity : AppCompatActivity() { protected lateinit var binding: VB - private var serialPort: SerialPort? = null - var outputStream: OutputStream? = null - private var inputStream: InputStream? = null - private var readThread: ReadThread? = null - inner class ReadThread : Thread() { - override fun run() { - super.run() - while (!isInterrupted) { - var size: Int - try { - val buffer = ByteArray(32) - if (inputStream == null) return - size = inputStream!!.read(buffer) - if (size > 0) { - onDataReceived(buffer, size) - } - } catch (e: IOException) { - e.printStackTrace() - return - } - } - } - } + lateinit var out: OutputStream override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,12 +30,50 @@ initEvent() try { - serialPort = BaseApplication.get().getSerialPort() - outputStream = serialPort?.outputStream - inputStream = serialPort?.inputStream + val serialPorts = BaseApplication.get().getSerialPorts() + //读 + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[0].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } - readThread = ReadThread() - readThread?.start() + lifecycleScope.launch(Dispatchers.IO) { + serialPorts?.apply { + val stream = this[1].inputStream + while (isActive) { + try { + val buffer = ByteArray(64) + val size = stream.read(buffer) + if (size > 0) { + withContext(Dispatchers.Main) { + onDataReceived(buffer) + } + } + } catch (e: IOException) { + e.printStackTrace() + } + } + } + } + + //写 + serialPorts?.apply { + out = this[0].outputStream + } } catch (e: SecurityException) { "您没有串口的读写权限!".show(this) } catch (e: IOException) { @@ -90,14 +109,12 @@ abstract fun initEvent() /** - * 串口读数 + * 串口读数,已经切回主线程 * */ - abstract fun onDataReceived(buffer: ByteArray?, size: Int) + abstract fun onDataReceived(buffer: ByteArray) override fun onDestroy() { - super.onDestroy() - readThread?.interrupt() BaseApplication.get().closeSerialPort() - serialPort = null + super.onDestroy() } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt new file mode 100644 index 0000000..c96c6f5 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/AMapLocation.kt @@ -0,0 +1,59 @@ +package com.casic.electric.detector.extensions + +import com.amap.api.location.AMapLocation +import com.amap.api.maps.AMapUtils +import com.amap.api.maps.model.LatLng +import com.casic.electric.detector.model.CalculateResult +import kotlin.math.acos + +/** + * 计算两个经纬度之间连线的方位角,因为距离很近(一般是3米内),球面近似为平面 + * C B + * |-------/ + * | / + * | / + * | / + * | / + * | / + * | / + * |/ + * A + * */ +fun AMapLocation.calculateAngle(target: LatLng): CalculateResult { + //构造直角辅助点 + val auxiliaryPoint = LatLng(target.latitude, this.longitude) + + //AB线段长度 + val distance = AMapUtils.calculateLineDistance( + LatLng(this.latitude, this.longitude), target + ) + + //AC线段长度 + val auxiliaryDistance = AMapUtils.calculateLineDistance( + LatLng(auxiliaryPoint.latitude, auxiliaryPoint.longitude), target + ) + + //求余弦值 + val cosine = auxiliaryDistance / distance + + //反余弦得弧度 + val radian = acos(cosine) + + //弧度转角度,度=弧度×180°/π + val angle = (radian * 180) / Math.PI + + //判断方位 + val direction = if (target.latitude > this.latitude && target.longitude > this.longitude) { + //东北方 + "东偏北" + } else if (target.latitude < this.latitude && target.longitude < this.longitude) { + //西南方 + "西偏南" + } else if (target.latitude > this.latitude && target.longitude < this.longitude) { + //西北方 + "西偏北" + } else { + "东偏南" + } + return CalculateResult(angle.toInt(), direction, distance.toInt()) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt b/app/src/main/java/com/casic/electric/detector/extensions/Context.kt deleted file mode 100644 index fcf36a7..0000000 --- a/app/src/main/java/com/casic/electric/detector/extensions/Context.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.casic.electric.detector.extensions - -import android.content.Context -import android.view.ViewGroup -import com.pengxh.kt.lite.extensions.getStatusBarHeight - -/** - * 设置沉浸式状态栏,兼容Android 11+ - * */ -fun Context.initLayoutImmersionBar(rootView: ViewGroup) { - rootView.setPadding(0, this.getStatusBarHeight(), 0, 0) - rootView.requestLayout() -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt index 6e08b27..e98408a 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/Int.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/Int.kt @@ -13,12 +13,4 @@ paint.color = color canvas.drawArc(rectF, 0f, 360f, true, paint) return bitmap -} - -fun Int.appendZero(): String { - return if (this < 10) { - "0$this" - } else { - this.toString() - } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/String.kt b/app/src/main/java/com/casic/electric/detector/extensions/String.kt index a0db0eb..838d3ad 100644 --- a/app/src/main/java/com/casic/electric/detector/extensions/String.kt +++ b/app/src/main/java/com/casic/electric/detector/extensions/String.kt @@ -3,14 +3,11 @@ import android.content.Context import android.widget.TextView import com.casic.electric.detector.callback.OnImageCompressListener -import com.casic.electric.detector.model.ErrorMessageModel import com.casic.electric.detector.utils.FileType import com.casic.electric.detector.utils.LocaleConstant -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken +import com.google.gson.JsonParser import com.pengxh.kt.lite.extensions.createCompressImageDir import com.pengxh.kt.lite.utils.SaveKeyValues -import org.json.JSONObject import top.zibin.luban.Luban import top.zibin.luban.OnCompressListener import java.io.File @@ -18,18 +15,22 @@ /** * String扩展方法 */ -fun String.separateResponseState(): Boolean { +fun String.getResponseState(): Boolean { if (this.isBlank()) { return false } - return JSONObject(this).getBoolean("success") + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("success").asBoolean } -fun String.toErrorMessage(): String { - val errorModel = Gson().fromJson( - this, object : TypeToken() {}.type - ) - return errorModel.message.toString() +fun String.getResponseMessage(): String { + if (this.isBlank()) { + return "" + } + val element = JsonParser.parseString(this) + val jsonObject = element.asJsonObject + return jsonObject.get("message").asString } /** @@ -131,4 +132,9 @@ } else { "6" } +} + +fun String.isNumber(): Boolean { + val regex = Regex("[-+]?\\d+(\\.\\d+)?") + return this.matches(regex) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt new file mode 100644 index 0000000..8b78a3c --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/extensions/ViewGroup.kt @@ -0,0 +1,31 @@ +package com.casic.electric.detector.extensions + +import android.app.Activity +import android.view.ViewGroup +import androidx.annotation.ColorRes +import androidx.fragment.app.Fragment +import com.gyf.immersionbar.ImmersionBar +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.getStatusBarHeight + +fun ViewGroup.initImmersionBar(activity: Activity, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(activity) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(activity)) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = activity.getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} + +fun ViewGroup.initImmersionBar(fragment: Fragment, isDarkFont: Boolean, @ColorRes color: Int) { + ImmersionBar.with(fragment) + .statusBarDarkFont(isDarkFont) + .statusBarColorInt(color.convertColor(fragment.requireContext())) + .init() + //根据不同设备状态栏高度设置statusBarView高度 + val statusBarHeight = fragment.requireContext().getStatusBarHeight() + this.setPadding(0, statusBarHeight, 0, 0) + this.requestLayout() +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt new file mode 100644 index 0000000..84c9cd9 --- /dev/null +++ b/app/src/main/java/com/casic/electric/detector/model/CalculateResult.kt @@ -0,0 +1,3 @@ +package com.casic.electric.detector.model + +data class CalculateResult(val angle: Int, val direction: String, val distance: Int) diff --git a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java b/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java deleted file mode 100644 index 1574393..0000000 --- a/app/src/main/java/com/casic/electric/detector/model/ErrorMessageModel.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.casic.electric.detector.model; - -public class ErrorMessageModel { - private int code; - private String data; - private String exceptionClazz; - private String message; - private boolean isSuccess; - - public int getCode() { - return code; - } - - public void setCode(int code) { - this.code = code; - } - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public String getExceptionClazz() { - return exceptionClazz; - } - - public void setExceptionClazz(String exceptionClazz) { - this.exceptionClazz = exceptionClazz; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public boolean isSuccess() { - return isSuccess; - } - - public void setSuccess(boolean success) { - isSuccess = success; - } -} diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt index 950fb91..f590226 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitService.kt @@ -90,10 +90,25 @@ /** * 上传工单中标识器信息 + * info中的主键 */ @GET("/ems/rs/task/update-task-mark") suspend fun uploadMarker( - @Query("userName") userId: String, - @Query("taskDetailId") taskId: String, + @Query("taskDetailId") taskId: String ): String + + /** + * 新建自由巡检任务 + * */ + @GET("ems/rs/task/addAppTask") + suspend fun createFreeTask( + @Query("patrollerId") patrollerId: String, + @Query("description") description: String + ): String + + /** + * 上传自由巡检过程中发现的标识器 + * */ + @POST("ems/event/uploadAppMarker.do") + suspend fun uploadTaskMarker(@Body requestBody: RequestBody): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt index 6834fc5..7836b28 100644 --- a/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/electric/detector/retrofit/RetrofitServiceManager.kt @@ -1,5 +1,6 @@ package com.casic.electric.detector.retrofit +import com.casic.electric.detector.extensions.reformat import com.casic.electric.detector.utils.LabelDataClass import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.SmallLabelDataClass @@ -15,43 +16,32 @@ object RetrofitServiceManager { + private fun createApi(): RetrofitService { + val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String + val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String + val httpConfig = "http://${serverIp}:${serverPort}" + return RetrofitFactory.createRetrofit(httpConfig) + } + /** * 登录 */ suspend fun login(account: String, password: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.login(account, password) + return createApi().login(account, password) } /** * 更新版本 * */ suspend fun getApplicationVersion(): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getApplicationVersion() + return createApi().getApplicationVersion() } /** * 获取标识器信息文件 */ suspend fun getMarkerFile(userId: String, companyId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getMarkerFile(userId, companyId) + return createApi().getMarkerFile(userId, companyId) } /** @@ -64,39 +54,21 @@ "application/json;charset=UTF-8".toMediaType() ) - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getLabelPicture(requestBody) + return createApi().getLabelPicture(requestBody) } /** * 获取巡检工单 */ suspend fun getTask(userName: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.getTask(userName) + return createApi().getTask(userName) } /** * 提交工单 */ suspend fun uploadTask(userId: String, taskId: String?, state: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadTask(userId, taskId.toString(), state) + return createApi().uploadTask(userId, taskId.toString(), state) } /** @@ -164,27 +136,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installLabel(res, multiParts[0], multiParts[1], null) + createApi().installLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installLabel(res, multiParts[0], null, null) + createApi().installLabel(res, multiParts[0], null, null) } else -> { - api.installLabel(res, null, null, null) + createApi().installLabel(res, null, null, null) } } } @@ -230,27 +196,21 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], multiParts[2]) } 2 -> { - api.installSmallLabel(res, multiParts[0], multiParts[1], null) + createApi().installSmallLabel(res, multiParts[0], multiParts[1], null) } 1 -> { - api.installSmallLabel(res, multiParts[0], null, null) + createApi().installSmallLabel(res, multiParts[0], null, null) } else -> { - api.installSmallLabel(res, null, null, null) + createApi().installSmallLabel(res, null, null, null) } } } @@ -279,27 +239,23 @@ multiParts.add(fileMultipart) } - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } return when (multiParts.size) { 3 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2]) + createApi().uploadEvent( + taskIdMap, eventMap, multiParts[0], multiParts[1], multiParts[2] + ) } 2 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], multiParts[1], null) } 1 -> { - api.uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) + createApi().uploadEvent(taskIdMap, eventMap, multiParts[0], null, null) } else -> { - api.uploadEvent(taskIdMap, eventMap, null, null, null) + createApi().uploadEvent(taskIdMap, eventMap, null, null, null) } } } @@ -307,13 +263,27 @@ /** * 上传工单中标识器信息 */ - suspend fun uploadMarker(userName: String, taskDetailId: String): String { - val api by lazy { - val serverIp = SaveKeyValues.getValue(LocaleConstant.SERVER_IP, "") as String - val serverPort = SaveKeyValues.getValue(LocaleConstant.SERVER_PORT, "") as String - val httpConfig = "http://${serverIp}:${serverPort}" - RetrofitFactory.createRetrofit(httpConfig) - } - return api.uploadMarker(userName, taskDetailId) + suspend fun uploadMarker(taskDetailId: String): String { + return createApi().uploadMarker(taskDetailId) + } + + /** + * 上传工单中标识器信息 + */ + suspend fun createFreeTask(patrollerId: String, description: String): String { + return createApi().createFreeTask(patrollerId, description) + } + + /** + * 上传自由巡检过程中发现的标识器 + */ + suspend fun uploadTaskMarker(taskId: String, models: ArrayList): String { + val param = JsonObject() + param.addProperty("taskId", taskId) + param.addProperty("ids", models.reformat()) + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + return createApi().uploadTaskMarker(requestBody) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java index 4aba809..45d5a2f 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java +++ b/app/src/main/java/com/casic/electric/detector/utils/GpioManager.java @@ -1,8 +1,10 @@ package com.casic.electric.detector.utils; -public class GpioManager { +import android.util.Log; +public class GpioManager { + private static final String TAG = "GpioManager"; private static final int MT6761 = 0; private int selected; private final MT6761Gpio mt6761; @@ -38,6 +40,7 @@ * 璁剧疆GPIO杈撳嚭楂� * *********************************************************************/ public void setGpioHigh(String gpio) { + Log.d(TAG, "setGpioHigh: 调高电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioHigh(); @@ -48,6 +51,7 @@ * 璁剧疆GPIO杈撳嚭浣� * *********************************************************************/ public void setGpioLow(String gpio) { + Log.d(TAG, "setGpioLow: 调低电位"); if (this.getSelected() == MT6761) { mt6761.setCtrlPin(gpio); mt6761.setGpioLow(); diff --git a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt deleted file mode 100644 index c589c4b..0000000 --- a/app/src/main/java/com/casic/electric/detector/utils/LoadingDialogHub.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.casic.electric.detector.utils - -import android.app.Activity -import android.view.WindowManager -import com.qmuiteam.qmui.widget.dialog.QMUITipDialog - -object LoadingDialogHub { - - private lateinit var loadingDialog: QMUITipDialog - - fun show(activity: Activity, message: String) { - loadingDialog = QMUITipDialog - .Builder(activity) - .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING) - .setTipWord(message) - .create() - if (!activity.isDestroyed) { - try { - loadingDialog.show() - } catch (e: WindowManager.BadTokenException) { - e.printStackTrace() - } - } - } - - fun dismiss() { - if (loadingDialog.isShowing) { - loadingDialog.dismiss() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt index 4de12f2..9356f9a 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocaleConstant.kt @@ -13,7 +13,7 @@ ) const val PERMISSIONS_CODE = 999 - const val RADIUS_SIZE = 100f //相距多少米才聚合,单位:米 + const val RADIUS_SIZE = 100 //相距多少米才聚合,单位:米 const val AUTO_SAVE = "AUTO_SAVE" const val USER_ACCOUNT = "USER_ACCOUNT" @@ -28,10 +28,21 @@ const val APP_AUTHORITY = "com.casic.electric.detector.fileprovider" val POPUP_TITLES = arrayOf("更新数据", "下载工单", "关于软件", "事件上报", "标识器补全") - var CONDITION_ARRAY = arrayOf("种类", "编号", "名称", "所属区域", "所属道路", "运检单位", "责任人", "建设时间", "标识器ID") + var CONDITION_ARRAY = arrayOf( + "种类", + "编号", + "名称", + "所属区域", + "所属道路", + "运检单位", + "责任人", + "建设时间", + "标识器ID" + ) var CONTENT_ARRAY = arrayOf("电缆井", "电缆通道", "配电房", "开关站", "台区", "杆塔") var OBJECT_MODE_ARRAY = arrayOf("直线井", "转弯井", "丁字井", "十字井", "其他") - var WELL_COVER_MATERIAL_ARRAY_1 = arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") + var WELL_COVER_MATERIAL_ARRAY_1 = + arrayOf("水泥盖板", "双重加重铁盖", "普通复合盖", "轻型连盖", "长方铁盖", "其他") var WELL_COVER_MATERIAL_ARRAY_2 = arrayOf("水泥杆", "钢管杆", "铁塔", "其他") var CABINET_TYPE_ARRAY = arrayOf("无", "SM6", "SAFE", "RM6", "XGN15", "固体柜") var PIPE_MATERIAL_ARRAY = arrayOf("无", "PVC管", "波纹管", "镀锌钢管") @@ -42,7 +53,16 @@ var CROSS_PIPE_STATE_ARRAY = booleanArrayOf(false, false, false, false, false, false, false) var POINT_TYPE_ARRAY = arrayOf("管线", "管线附属物", "管线特征管点", "交叉穿越点") - var SPINNER_ARRAY = arrayOf("标识器ID", "所属区域", "所属线路", "所属道路", "权属单位", "安装部门", "安装时间", "备注") + var SPINNER_ARRAY = arrayOf( + "标识器ID", + "所属区域", + "所属线路", + "所属道路", + "权属单位", + "安装部门", + "安装时间", + "备注" + ) var DOWN_PIPE_TYPE_ARRAY = arrayOf("热力", "燃气", "供水", "电力", "通信") var BURY_METHOD_ARRAY = arrayOf("直埋", "圆管", "管块", "管沟", "架空") var COLOR_ARRAY = arrayOf("蓝色", "橙色", "红色", "黑色", "紫色", "黄色", "绿色") diff --git a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt index 4f0f2c7..61e55f6 100644 --- a/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt +++ b/app/src/main/java/com/casic/electric/detector/utils/LocationHub.kt @@ -14,14 +14,16 @@ import com.casic.electric.detector.callback.IAddressListener import com.casic.electric.detector.callback.ILocationListener -object LocationHub { - private const val kTag = "LocationHub" +class LocationHub constructor(context: Context) { - fun getCurrentLocation(context: Context, listener: ILocationListener) { - val locationClient = AMapLocationClient(context) + private val kTag = "LocationHub" + private val locationClient by lazy { AMapLocationClient(context) } + private val codeSearch by lazy { GeocodeSearch(context) } + + fun getCurrentLocation(isOnceLocation: Boolean, listener: ILocationListener) { val locationOption = AMapLocationClientOption() locationOption.locationMode = AMapLocationClientOption.AMapLocationMode.Hight_Accuracy - locationOption.isOnceLocation = true + locationOption.isOnceLocation = isOnceLocation locationClient.setLocationOption(locationOption) locationClient.setLocationListener { if (it.errorCode == 0) { @@ -36,9 +38,8 @@ locationClient.startLocation() } - fun antiCodingLocation(context: Context, location: Location, listener: IAddressListener) { + fun antiCodingLocation(location: Location, listener: IAddressListener) { try { - val codeSearch = GeocodeSearch(context) // 第一个参数表示一个LatLonPoint,第二参数表示范围多少米,第三个参数表示是火系坐标系还是GPS原生坐标系 val query = RegeocodeQuery( LatLonPoint(location.latitude, location.longitude), 10f, GeocodeSearch.AMAP @@ -55,4 +56,8 @@ e.printStackTrace() } } + + fun stopLocation() { + locationClient.stopLocation() + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt b/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt index aa1bdeb..e3d3289 100644 --- a/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/BigImageActivity.kt @@ -1,7 +1,6 @@ package com.casic.electric.detector.view import android.content.Context -import android.graphics.Color import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -12,10 +11,10 @@ import com.bumptech.glide.Glide import com.casic.electric.detector.R import com.casic.electric.detector.databinding.ActivityBigImageBinding +import com.casic.electric.detector.extensions.initImmersionBar import com.luck.picture.lib.photoview.PhotoView import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.ImmerseStatusBarUtil class BigImageActivity : KotlinBaseActivity() { @@ -24,20 +23,12 @@ } override fun setupTopBarLayout() { - ImmerseStatusBarUtil.setColor(this, Color.BLACK) + binding.rootView.initImmersionBar(this, false, R.color.black) binding.leftBackView.setOnClickListener { finish() } } override fun initOnCreate(savedInstanceState: Bundle?) { - - } - - override fun observeRequestState() { - - } - - override fun initEvent() { - val index: Int = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) + val index = intent.getIntExtra(Constant.BIG_IMAGE_INTENT_INDEX_KEY, 0) val urls = intent.getStringArrayListExtra(Constant.BIG_IMAGE_INTENT_DATA_KEY) if (urls == null || urls.size == 0) { return @@ -62,6 +53,14 @@ }) } + override fun observeRequestState() { + + } + + override fun initEvent() { + + } + inner class BigImageAdapter( private val context: Context, private val data: ArrayList ) : PagerAdapter() { diff --git a/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt b/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt index d3a89ca..6510104 100644 --- a/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/InstallLabelActivity.kt @@ -29,15 +29,15 @@ import com.casic.electric.detector.extensions.* import com.casic.electric.detector.utils.* import com.casic.electric.detector.vm.TaskViewModel -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia import com.luck.picture.lib.interfaces.OnResultCallbackListener import com.pengxh.kt.lite.extensions.* +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -53,7 +53,8 @@ private val context: Context = this@InstallLabelActivity private val gpioManager by lazy { GpioManager() } private val calendar by lazy { Calendar.getInstance() } - private val realPaths: ArrayList = ArrayList() //真实图片路径 + private val locationHub by lazy { LocationHub(this) } + private val realPaths = ArrayList() //真实图片路径 private var soundResId = 0 private lateinit var weakReferenceHandler: WeakReferenceHandler private lateinit var soundPool: SoundPool @@ -67,12 +68,6 @@ override fun setupTopBarLayout() { binding.titleInclude.titleView.text = "安装新标识器" binding.titleInclude.titleView.setTextColor(R.color.themeColor.convertColor(this)) - - ImmersionBar.with(this) - .statusBarDarkFont(true) - .statusBarColor(R.color.mainBackground) - .init() - initLayoutImmersionBar(binding.rootView) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -126,7 +121,7 @@ binding.markerAttrInclude.remarkView3.setText("remarkView3".getDefaultValue()) //初始化图片九宫格 - imageAdapter = EditableImageAdapter(this, 3, 3f) + imageAdapter = EditableImageAdapter(this, 3, 3) binding.cameraInclude.addImageRecyclerView.adapter = imageAdapter taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] @@ -332,7 +327,7 @@ binding.markerAttrInclude.installTimeView.text = System.currentTimeMillis().timestampToCompleteDate() - LocationHub.getCurrentLocation(this, object : ILocationListener { + locationHub.getCurrentLocation(true, object : ILocationListener { override fun onAMapLocationGet(location: AMapLocation?) { if (location != null) { binding.markerAttrInclude.lngView.text = location.longitude.toString() @@ -518,8 +513,8 @@ weakReferenceHandler.postDelayed({ try { // 发送读标识器或搜索信号 - outputStream?.write("2".toByteArray()) - outputStream?.flush() + out.write("2".toByteArray()) + out.flush() } catch (e: IOException) { e.printStackTrace() } @@ -527,7 +522,7 @@ } } - override fun onDataReceived(buffer: ByteArray?, size: Int) { + override fun onDataReceived(buffer: ByteArray) { Log.d(kTag, "onDataReceived => " + buffer.contentToString()) if (buffer != null) { val message = weakReferenceHandler.obtainMessage() diff --git a/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt b/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt index 5bc2ac8..286bf4a 100644 --- a/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/InstallSmallLabelActivity.kt @@ -24,7 +24,6 @@ import com.casic.electric.detector.extensions.* import com.casic.electric.detector.utils.* import com.casic.electric.detector.vm.TaskViewModel -import com.gyf.immersionbar.ImmersionBar import com.luck.picture.lib.basic.PictureSelector import com.luck.picture.lib.config.SelectMimeType import com.luck.picture.lib.entity.LocalMedia @@ -33,9 +32,10 @@ import com.pengxh.kt.lite.extensions.isNetworkConnected import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -65,12 +65,6 @@ override fun setupTopBarLayout() { binding.titleInclude.titleView.text = "安装新电子标签" binding.titleInclude.titleView.setTextColor(R.color.themeColor.convertColor(this)) - - ImmersionBar.with(this) - .statusBarDarkFont(true) - .statusBarColor(R.color.mainBackground) - .init() - initLayoutImmersionBar(binding.rootView) } override fun initOnCreate(savedInstanceState: Bundle?) { @@ -103,7 +97,7 @@ binding.objectAttrInclude.objectRemarkView3.setText("objectRemarkView3".getDefaultValue()) //初始化图片九宫格 - imageAdapter = EditableImageAdapter(this, 3, 3f) + imageAdapter = EditableImageAdapter(this, 3, 3) binding.cameraInclude.addImageRecyclerView.adapter = imageAdapter taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] @@ -308,8 +302,8 @@ weakReferenceHandler.postDelayed({ try { // 发送读标识器或搜索信号 - outputStream?.write("2".toByteArray()) - outputStream?.flush() + out.write("2".toByteArray()) + out.flush() } catch (e: IOException) { e.printStackTrace() } @@ -317,7 +311,7 @@ } } - override fun onDataReceived(buffer: ByteArray?, size: Int) { + override fun onDataReceived(buffer: ByteArray) { if (buffer != null) { val message = weakReferenceHandler.obtainMessage() message.what = 2023081702 diff --git a/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt b/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt index 44d56ef..9c98b5f 100644 --- a/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/LoginActivity.kt @@ -1,36 +1,29 @@ package com.casic.electric.detector.view import android.os.Bundle -import android.util.Log import androidx.lifecycle.ViewModelProvider import com.amap.api.navi.NaviSetting import com.casic.electric.detector.databinding.ActivityLoginBinding -import com.casic.electric.detector.extensions.initLayoutImmersionBar -import com.casic.electric.detector.utils.GpioManager -import com.casic.electric.detector.utils.LoadingDialogHub import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.vm.UserViewModel import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.extensions.getScreenHeight -import com.pengxh.kt.lite.extensions.getScreenWidth import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues -import com.pengxh.kt.lite.vm.LoadState import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog class LoginActivity : KotlinBaseActivity() { private val kTag = "LoginActivity" private lateinit var userViewModel: UserViewModel - private val gpioManager by lazy { GpioManager() } override fun initViewBinding(): ActivityLoginBinding { return ActivityLoginBinding.inflate(layoutInflater) } override fun initOnCreate(savedInstanceState: Bundle?) { - gpioManager.setGpioLow("18") //先把导航隐私政策声明,后面导航会用到 NaviSetting.updatePrivacyShow(this, true, true) NaviSetting.updatePrivacyAgree(this, true) @@ -60,11 +53,8 @@ val serversIp = binding.serversIpView.text.toString() val serversPort = binding.serversPortView.text.toString() if (account.isBlank() || password.isBlank() || serversIp.isBlank() || serversPort.isBlank()) { - AlertMessageDialog.Builder() - .setContext(this) - .setTitle("账号登录") - .setMessage("信息不能为空哦!") - .setPositiveButton("知道了") + AlertMessageDialog.Builder().setContext(this).setTitle("账号登录") + .setMessage("信息不能为空哦!").setPositiveButton("知道了") .setOnDialogButtonClickListener(object : AlertMessageDialog.OnDialogButtonClickListener { override fun onConfirmClick() { @@ -102,9 +92,6 @@ override fun setupTopBarLayout() { ImmersionBar.with(this).statusBarDarkFont(true).init() - initLayoutImmersionBar(binding.rootView) - - Log.d(kTag, "setupTopBarLayout => [${getScreenWidth()}, ${getScreenHeight()}]") } override fun onResume() { diff --git a/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt b/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt index 36a8d55..a0a4aac 100644 --- a/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/MainActivity.kt @@ -1,15 +1,21 @@ package com.casic.electric.detector.view +import android.annotation.SuppressLint import android.app.AlertDialog +import android.app.Dialog import android.content.Context -import android.content.Intent import android.graphics.Color import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable +import android.media.AudioAttributes +import android.media.SoundPool import android.os.Bundle -import android.os.PowerManager -import android.provider.Settings +import android.os.CountDownTimer +import android.util.Log import android.view.KeyEvent +import android.view.View +import android.view.animation.Animation +import android.view.animation.RotateAnimation import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import com.amap.api.location.AMapLocation @@ -21,6 +27,8 @@ import com.amap.api.maps.model.LatLngBounds import com.amap.api.maps.model.MyLocationStyle import com.casic.electric.detector.R +import com.casic.electric.detector.adapter.EditableImageAdapter +import com.casic.electric.detector.base.SerialPortActivity import com.casic.electric.detector.bean.LabelBean import com.casic.electric.detector.bean.SmallLabelBean import com.casic.electric.detector.bean.TaskBean @@ -29,83 +37,109 @@ import com.casic.electric.detector.cluster.ClusterOverlay import com.casic.electric.detector.cluster.RegionItem import com.casic.electric.detector.databinding.ActivityMainBinding +import com.casic.electric.detector.databinding.DialogInstallMarkerBinding +import com.casic.electric.detector.databinding.DialogInstallSmallMarkerBinding +import com.casic.electric.detector.databinding.DialogSearchMarkerBinding import com.casic.electric.detector.extensions.appendExcelDownloadUrl import com.casic.electric.detector.extensions.drawCircle -import com.casic.electric.detector.extensions.initLayoutImmersionBar +import com.casic.electric.detector.extensions.hexToString +import com.casic.electric.detector.extensions.initImmersionBar +import com.casic.electric.detector.extensions.isNumber +import com.casic.electric.detector.extensions.toHex import com.casic.electric.detector.utils.DataBaseManager import com.casic.electric.detector.utils.ExcelHub -import com.casic.electric.detector.utils.LoadingDialogHub +import com.casic.electric.detector.utils.GpioManager import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.LocationHub import com.casic.electric.detector.utils.RouteOnMap import com.casic.electric.detector.vm.TaskViewModel import com.casic.electric.detector.widgets.QueryMarkerDialog import com.casic.electric.detector.widgets.SamplePopupWindow -import com.gyf.immersionbar.ImmersionBar -import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.callback.OnDownloadListener +import com.google.gson.Gson +import com.pengxh.kt.lite.extensions.binding import com.pengxh.kt.lite.extensions.createDownloadFileDir -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.dp2px +import com.pengxh.kt.lite.extensions.initDialogLayoutParams import com.pengxh.kt.lite.extensions.isNetworkConnected import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.extensions.toJson +import com.pengxh.kt.lite.utils.FileDownloadManager +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertControlDialog +import com.pengxh.kt.lite.widget.dialog.AlertInputDialog +import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog import com.pengxh.kt.lite.widget.dialog.BottomActionSheet -import com.pengxh.kt.lite.widget.dialog.NoNetworkDialog -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File +import java.text.DecimalFormat +import java.util.Calendar +import java.util.Timer +import java.util.TimerTask -class MainActivity : KotlinBaseActivity() { +@SuppressLint("all") +class MainActivity : SerialPortActivity() { private val kTag = "MainActivity" - private val context: Context = this@MainActivity + private val context = this@MainActivity + private val gpioManager by lazy { GpioManager() } private val samplePopupWindow by lazy { SamplePopupWindow(this) } + private val gson by lazy { Gson() } + private val locationHub by lazy { LocationHub(this) } + private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } + private val backDrawables by lazy { HashMap() } + private val installMarkerDialog by lazy { InstallMarkerDialog(this) } + private val installSmallMarkerDialog by lazy { InstallSmallMarkerDialog(this) } + private val searchDialog by lazy { SearchMarkerDialog(this) } private var clickTime: Long = 0 - private lateinit var wakeLock: PowerManager.WakeLock - private lateinit var aMap: AMap - private lateinit var taskViewModel: TaskViewModel - private lateinit var taskBean: TaskBean - private var latitude: Double = 0.0 - private var longitude: Double = 0.0 private var labels = ArrayList() private var smallLabels = ArrayList() private var clusterOverlay: ClusterOverlay? = null - private val backDrawables = HashMap() - private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } + private var latitude: Double = 0.0 + private var longitude: Double = 0.0 + private var isFreeTask = false + private var ids = ArrayList() + private var signalTask: TimerTask? = null + private var searchMarkerTimer: Timer? = null + private lateinit var aMap: AMap + private lateinit var taskBean: TaskBean + private lateinit var taskId: String + + /***inner class 需要用到*****start*/ + private val taskViewModel by lazy { ViewModelProvider(this)[TaskViewModel::class.java] } + 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 var soundResourceId = 0 + private var slowSoundResourceId = 0 + private var fastSoundResourceId = 0 + + /***inner class 需要用到*****end*/ override fun initViewBinding(): ActivityMainBinding { return ActivityMainBinding.inflate(layoutInflater) } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(false).statusBarColor(R.color.themeColor).init() - initLayoutImmersionBar(binding.rootView) - } - - override fun observeRequestState() { - + binding.rootView.initImmersionBar(this, false, R.color.themeColor) } override fun initOnCreate(savedInstanceState: Bundle?) { - val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager - wakeLock = powerManager.run { - newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this@MainActivity.localClassName).apply { - acquire(60 * 60 * 1000L) - } - } + soundResourceId = soundPool.load(this, R.raw.ring3, 1) + slowSoundResourceId = soundPool.load(this, R.raw.ring4, 1) + fastSoundResourceId = soundPool.load(this, R.raw.ring2, 1) + //地图初始化 initMapConfig(savedInstanceState) samplePopupWindow.setPopupMenuItem(LocaleConstant.POPUP_TITLES) samplePopupWindow.setBackgroundDrawable(null) - taskViewModel = ViewModelProvider(this)[TaskViewModel::class.java] + //task网络请求监听 taskViewModel.markerFileResult.observe(this) { if (it.success == "true") { //清空之前的数据 @@ -122,11 +156,13 @@ val smallLabelDownloadUrl = urlArray[1].appendExcelDownloadUrl() //下载标识器 - labelDownloadUrl.downloadFile( - createDownloadFileDir().toString(), object : OnDownloadListener { - override fun onDownloadEnd(file: File?) { + FileDownloadManager.Builder().setDownloadFileSource(labelDownloadUrl) + .setFileSuffix("xls").setFileSaveDirectory(createDownloadFileDir()) + .setOnFileDownloadListener(object : + FileDownloadManager.OnFileDownloadListener { + override fun onDownloadEnd(file: File) { lifecycleScope.launch { - labels = ExcelHub.readLabel(file?.absolutePath) + labels = ExcelHub.readLabel(file.absolutePath) withContext(Dispatchers.IO) { labels.forEach { label -> DataBaseManager.get.insertLabel(label) @@ -137,21 +173,23 @@ } } - override fun onDownloadStart(totalBytes: Long) { + override fun onFailure(throwable: Throwable) { } - override fun onProgressChanged(currentBytes: Long) { + override fun onProgressChanged(progress: Int) { } - }) + }).build().start() //下载附属标识器 - smallLabelDownloadUrl.downloadFile( - createDownloadFileDir().toString(), object : OnDownloadListener { - override fun onDownloadEnd(file: File?) { + FileDownloadManager.Builder().setDownloadFileSource(smallLabelDownloadUrl) + .setFileSuffix("xls").setFileSaveDirectory(createDownloadFileDir()) + .setOnFileDownloadListener(object : + FileDownloadManager.OnFileDownloadListener { + override fun onDownloadEnd(file: File) { lifecycleScope.launch { - smallLabels = ExcelHub.readSmallLabel(file?.absolutePath) + smallLabels = ExcelHub.readSmallLabel(file.absolutePath) withContext(Dispatchers.IO) { smallLabels.forEach { label -> DataBaseManager.get.insertSmallLabel(label) @@ -160,14 +198,14 @@ } } - override fun onDownloadStart(totalBytes: Long) { + override fun onFailure(throwable: Throwable) { } - override fun onProgressChanged(currentBytes: Long) { + override fun onProgressChanged(progress: Int) { } - }) + }).build().start() } } } @@ -175,11 +213,8 @@ // if (it.success == "true") { // //清空之前的数据 // DataBaseManager.get.clearTasks() -// AlertMessageDialog.Builder() -// .setContext(this) -// .setTitle("温馨提示") -// .setMessage("您有${it.message.size}个新任务!") -// .setPositiveButton("知道了") +// AlertMessageDialog.Builder().setContext(this).setTitle("温馨提示") +// .setMessage("您有${it.message.size}个新任务!").setPositiveButton("知道了") // .setOnDialogButtonClickListener(object : // AlertMessageDialog.OnDialogButtonClickListener { // override fun onConfirmClick() { @@ -188,19 +223,24 @@ // }).build().show() // } // } + taskViewModel.freeTaskResult.observe(this) { taskId = it } + taskViewModel.uploadTaskMarkerResult.observe(this) { + "自由巡检任务已完成".show(this) + ids.clear() + } } override fun initEvent() { binding.rightImageView.setOnClickListener { - CoroutineScope(Dispatchers.Main).launch { + lifecycleScope.launch(Dispatchers.Main) { val labels = withContext(Dispatchers.IO) { DataBaseManager.get.queryLabelById("0") } if (labels.isNotEmpty()) { samplePopupWindow.setShowPosition(4) } - val x = binding.rightImageView.width - samplePopupWindow.width - 1f.dp2px(context) - samplePopupWindow.showAsDropDown(binding.rightImageView, x, 1f.dp2px(context)) + val x = binding.rightImageView.width - samplePopupWindow.width - 1.dp2px(context) + samplePopupWindow.showAsDropDown(binding.rightImageView, x, 1.dp2px(context)) } } @@ -219,35 +259,33 @@ //安装。上传,然后存入本地库 binding.installButton.setOnClickListener { - AlertControlDialog.Builder() - .setContext(context) - .setTitle("提示") - .setMessage("请选择安装对象") - .setPositiveButton("标识器") - .setNegativeButton("电子标签") - .setOnDialogButtonClickListener(object : + AlertControlDialog.Builder().setContext(context).setTitle("提示") + .setMessage("请选择安装对象").setPositiveButton("标识器") + .setNegativeButton("电子标签").setOnDialogButtonClickListener(object : AlertControlDialog.OnDialogButtonClickListener { override fun onConfirmClick() { //标识器 - navigatePageTo() + /** + * 改为Dialog方式,避免频繁打开/关闭串口 + * */ + installMarkerDialog.show() } override fun onCancelClick() { //电子标签 - navigatePageTo() + /** + * 改为Dialog方式,避免频繁打开/关闭串口 + * */ + installSmallMarkerDialog.show() } }).build().show() } //查看 binding.viewButton.setOnClickListener { - QueryMarkerDialog.Builder() - .setContext(this) - .setTitle("查看标识器") - .setConditionArray(LocaleConstant.CONDITION_ARRAY) - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : + QueryMarkerDialog.Builder().setContext(this).setTitle("查看标识器") + .setConditionArray(LocaleConstant.CONDITION_ARRAY).setNegativeButton("取消") + .setPositiveButton("确定").setOnDialogButtonClickListener(object : QueryMarkerDialog.OnDialogButtonClickListener { override fun onConfirmClick( selectedCondition: String, vararg contentValue: String @@ -310,30 +348,25 @@ // arrayList.add("任务${index + 1}:${taskBean.taskId},${taskBean.desc}") // } // -// BottomActionSheet.Builder() -// .setContext(this) -// .setItemTextColor(Color.BLUE) +// BottomActionSheet.Builder().setContext(this).setItemTextColor(Color.BLUE) // .setActionItemTitle(arrayList) // .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { // override fun onActionItemClick(position: Int) { // val taskBean = task[position] // SaveKeyValues.putValue(LocaleConstant.TASK_ID, taskBean.taskId) -// AlertControlDialog.Builder() -// .setContext(context) -// .setTitle("提示") -// .setMessage("请选择操作方式") -// .setPositiveButton("执行工单") +// AlertControlDialog.Builder().setContext(context).setTitle("提示") +// .setMessage("请选择操作方式").setPositiveButton("执行工单") // .setNegativeButton("提交工单") // .setOnDialogButtonClickListener(object : // AlertControlDialog.OnDialogButtonClickListener { // override fun onConfirmClick() { // detectRedrawGraphic(taskBean.taskId) +// +// val latLng = LatLng( +// taskBean.lat.toDouble(), taskBean.lng.toDouble() +// ) // aMap.moveCamera( -// CameraUpdateFactory.newLatLngZoom( -// LatLng( -// taskBean.lat.toDouble(), taskBean.lng.toDouble() -// ), 15f -// ) +// CameraUpdateFactory.newLatLngZoom(latLng, 16f) // ) // uploadTask(taskBean.taskId, "1") // } @@ -345,15 +378,12 @@ // } // }).build().show() // } else { -// AlertMessageDialog.Builder() -// .setContext(this) -// .setTitle("温馨提示") -// .setMessage("现有任务已完成,请点击右上角菜单按钮下载新工单!") -// .setPositiveButton("知道了") -// .setOnDialogButtonClickListener(object : +// AlertMessageDialog.Builder().setContext(this).setTitle("温馨提示") +// .setMessage("现有任务已完成,请点击右上角菜单下载新工单或者开始自由巡检") +// .setPositiveButton("知道了").setOnDialogButtonClickListener(object : // AlertMessageDialog.OnDialogButtonClickListener { // override fun onConfirmClick() { -// +// startFreeTask() // } // }).build().show() // } @@ -361,7 +391,118 @@ //探测 binding.detectionButton.setOnClickListener { -// navigatePageTo() + /** + * 改为Dialog方式,避免频繁打开/关闭串口 + * */ + searchDialog.show() + } + + //自由巡检 + binding.stopFreeTaskButton.setOnLongClickListener { + AlertMessageDialog.Builder().setContext(this).setTitle("温馨提示") + .setMessage("是否确定结束此次自由巡检任务?").setPositiveButton("是") + .setOnDialogButtonClickListener(object : + AlertMessageDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + isFreeTask = false + soundPool.autoPause() + + //降低串口电位 + gpioManager.setGpioLow("18") + + taskViewModel.uploadTaskMarker(taskId, ids) + binding.stopFreeTaskButton.visibility = View.GONE + } + }).build().show() + true + } + } + + private fun startFreeTask() { + AlertInputDialog.Builder().setContext(this).setTitle("新建自由巡检任务") + .setHintMessage("请输入自由巡检任务简要描述").setNegativeButton("取消") + .setPositiveButton("确定") + .setOnDialogButtonClickListener(object : AlertInputDialog.OnDialogButtonClickListener { + override fun onConfirmClick(value: String) { + val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String + taskViewModel.createFreeTask(userId, value) + + //调高串口电位 + gpioManager.setGpioHigh("18") + + soundPool.play(soundResourceId, 1f, 1f, 0, -1, 1f) + isFreeTask = true + //自由巡检 + signalTask = object : TimerTask() { + override fun run() { + out.write('2'.code) + out.flush() + } + } + searchMarkerTimer = Timer() + searchMarkerTimer?.apply { + schedule(signalTask, 0, 100) + } + + binding.stopFreeTaskButton.visibility = View.VISIBLE + } + + override fun onCancelClick() {} + }).build().show() + } + + override fun onDataReceived(buffer: ByteArray) { + val hex = buffer.toHex() + Log.d(kTag, "$kTag => $hex") + if (searchDialog.isDetectMarker) { + searchDialog.bindingValue(hex) +// } else if (installMarkerDialog.isReadMarker) { +// val markerId = hex.take(20).hexToString() +// if (markerId.isNumber()) { +// installMarkerDialog.bindingValue(markerId) +// } +// } else if (installSmallMarkerDialog.isReadMarker) { +// val markerId = hex.take(20).hexToString() +// if (markerId.isNumber()) { +// installSmallMarkerDialog.bindingValue(markerId) +// } + } else if (isFreeTask) { + val markerId = hex.take(20).hexToString() + if (markerId.isNumber()) { + "标识器${markerId}已探测".show(this) + ids.add(markerId) + } + } + } + + override fun observeRequestState() { + taskViewModel.loadState.observe(this) { + when (it) { + LoadState.Loading -> { + if (installMarkerDialog.isInstallMarker || installSmallMarkerDialog.isInstallMarker) { + LoadingDialogHub.show(this, "标识器安装中,请稍后...") + } else if (searchDialog.isDetectMarker) { + searchDialog.taskBean?.apply { + "标识器${this.markerId}已探测!".show(context) +// DataBaseManager.get.updateTaskLabel(this) + } + } else { + LoadingDialogHub.show(this, "提交工单中,请稍后") + } + } + + else -> { + if (installMarkerDialog.isInstallMarker) { + installMarkerDialog.dismiss() + installMarkerDialog.isInstallMarker = false + } else if (installSmallMarkerDialog.isInstallMarker) { + installSmallMarkerDialog.dismiss() + installSmallMarkerDialog.isInstallMarker = false + } + LoadingDialogHub.dismiss() + } + } + detectRedrawGraphic(taskBean.taskId) } } @@ -375,6 +516,7 @@ uiSettings.isScaleControlsEnabled = true uiSettings.zoomPosition = AMapOptions.ZOOM_POSITION_RIGHT_CENTER uiSettings.isRotateGesturesEnabled = false//不许地图随手势旋转角度 + uiSettings.isTiltGesturesEnabled = false//不许地图随手势倾斜 //显示定位小蓝点 val locationStyle = MyLocationStyle() locationStyle.interval(2000) @@ -387,7 +529,7 @@ longitude = it.longitude latitude = it.latitude //经纬度逆编码 - LocationHub.antiCodingLocation(context, it) { address -> + locationHub.antiCodingLocation(it) { address -> binding.currentLocationView.text = address } } @@ -417,7 +559,7 @@ } private fun moveToCurrentLocation() { - LocationHub.getCurrentLocation(this, object : ILocationListener { + locationHub.getCurrentLocation(true, object : ILocationListener { override fun onAMapLocationGet(location: AMapLocation?) { if (location != null) { aMap.moveCamera( @@ -432,46 +574,35 @@ }) } - //更新数据 - private fun updateLabels() { - AlertControlDialog.Builder() - .setContext(this) - .setTitle("提示") - .setMessage("是否更新数据?") - .setNegativeButton("取消") - .setPositiveButton("确定") - .setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onConfirmClick() { - if (isNetworkConnected()) { - val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") - val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") - - LoadingDialogHub.show(this@MainActivity, "获取标识器信息中,请稍后") - //TODO 设计如此,都传companyId - taskViewModel.getMarkerFile(companyId.toString(), companyId.toString()) - } else { - NoNetworkDialog.Builder() - .setContext(context) - .setOnDialogButtonClickListener(object : - NoNetworkDialog.OnDialogButtonClickListener { - override fun onButtonClick() { - val intent = Intent(Settings.ACTION_SETTINGS) - startActivity(intent) - } - }).build().show() - } - } - - override fun onCancelClick() { - - } - }).build().show() - } +// private fun saveTaskInformation(it: TaskModel) { +// val userName = SaveKeyValues.getValue(LocaleConstant.USER_NAME, "") as String +// if (it.message.size > 0) { +// it.message.forEach { messageModel -> +// val count = DataBaseManager.get.countTaskById(messageModel.id.toString()) +// if (count == 0) { +// messageModel.taskDetailInfos.forEach { info -> +// DataBaseManager.get.insertTaskInformation( +// userName, +// messageModel.description, +// info.taskId.toString(), +// info.id.toString(), +// info.markerId.toString(), +// info.markerIdReal.toString(), +// info.longitude.toString(), +// info.latitude.toString(), +// messageModel.status +// ) +// } +// } +// } +// "工单下载成功!".show(context) +// } +// } private fun showLabelsOnMap() { clusterOverlay?.onDestroy() val clusterItems = ArrayList() + labels.forEach { val latLng = LatLng(it.latitude.toDouble(), it.longitude.toDouble(), false) val regionItem = RegionItem(latLng, it.markerId.toString()) @@ -480,7 +611,7 @@ clusterOverlay = ClusterOverlay(context, aMap, clusterItems, regionRadius) clusterOverlay?.setClusterRender { clusterNum -> - val radius = 80f.dp2px(context) + val radius = 80.dp2px(context) if (clusterNum == 0) { var bitmapDrawable = backDrawables[0] if (bitmapDrawable == null) { @@ -546,9 +677,7 @@ val latLngBounds = builder.build() aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 0)) - BottomActionSheet.Builder() - .setContext(this) - .setItemTextColor(Color.BLUE) + BottomActionSheet.Builder().setContext(this).setItemTextColor(Color.BLUE) .setActionItemTitle(listOf("标识器信息", "附属电子标签信息", "到这里去")) .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { override fun onActionItemClick(position: Int) { @@ -578,12 +707,7 @@ showElectricMarkers(electricMarkers) } - 2 -> { - RouteOnMap.startNavigation( - context, item.tag, - LatLng(item.position.latitude, item.position.longitude) - ) - } + 2 -> RouteOnMap.startNavigation(context, item.tag, latLng) } } }).build().show() @@ -591,14 +715,74 @@ } private fun showElectricMarkers(markers: ArrayList) { - AlertDialog.Builder(context) - .setIcon(R.mipmap.ic_launcher) - .setTitle("电子标签列表") + AlertDialog.Builder(context).setIcon(R.mipmap.ic_launcher).setTitle("电子标签列表") .setSingleChoiceItems(markers.toTypedArray(), -1) { _, which -> navigatePageTo(markers[which]) }.show() } + private fun detectRedrawGraphic(taskId: String) { +// val tasks = DataBaseManager.get.queryTaskById(taskId) +// if (tasks.isNotEmpty()) { +// tasks.forEach { +// val latLng = LatLng(it.lat.toDouble(), it.lng.toDouble()) +// val otMarkerOptions = MarkerOptions() +// otMarkerOptions.position(latLng) +// otMarkerOptions.visible(true) // 设置可见 +// if (it.state == "未开始") { +// otMarkerOptions.icon( +// BitmapDescriptorFactory.fromBitmap( +// BitmapFactory.decodeResource(resources, R.mipmap.label_red1) +// ) +// ).period(99).title("工单标识器").snippet(it.markerId) +// } else { +// otMarkerOptions.icon( +// BitmapDescriptorFactory.fromBitmap( +// BitmapFactory.decodeResource(resources, R.mipmap.label_blue1) +// ) +// ).period(99).title("工单标识器").snippet(it.markerId) +// } +// aMap.addMarker(otMarkerOptions) +// } +// } + showLabelsOnMap() + } + + private fun uploadTask(taskId: String?, state: String) { + if (isNetworkConnected()) { + val userId = SaveKeyValues.getValue(LocaleConstant.USER_ID, "") as String + taskViewModel.uploadTask(userId, taskId, state) + } else { + "网络连接已断开,请检查".show(this) + } + } + + //更新数据 + private fun updateLabels() { + AlertControlDialog.Builder().setContext(this).setTitle("提示").setMessage("是否更新数据?") + .setNegativeButton("取消").setPositiveButton("确定") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + if (isNetworkConnected()) { + val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") + + LoadingDialogHub.show(this@MainActivity, "获取标识器信息中,请稍后") + /** + * 后台设计如此,都传companyId + * */ + taskViewModel.getMarkerFile(companyId.toString(), companyId.toString()) + } else { + "网络连接已断开,请检查".show(context) + } + } + + override fun onCancelClick() { + + } + }).build().show() + } + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { return if (keyCode == KeyEvent.KEYCODE_BACK) { if (System.currentTimeMillis() - clickTime > 2000) { @@ -643,8 +827,270 @@ } override fun onDestroy() { - wakeLock.release() super.onDestroy() binding.mapView.onDestroy() + signalTask?.cancel() + searchMarkerTimer?.cancel() + soundPool.release() + locationHub.stopLocation() + //降低串口电位 + gpioManager.setGpioLow("18") + } + + /**安装标识器对话框******************************************************************************/ + inner class InstallMarkerDialog(context: Context) : Dialog(context) { + + private val binding: DialogInstallMarkerBinding by binding() + private val calendar by lazy { Calendar.getInstance() } + private val realPaths = ArrayList() //真实图片路径 + private lateinit var imageAdapter: EditableImageAdapter + + var isReadMarker = false + var isInstallMarker = false + } + + /**安装小标签对话框******************************************************************************/ + inner class InstallSmallMarkerDialog(context: Context) : Dialog(context) { + + private val binding: DialogInstallSmallMarkerBinding by binding() + private val calendar by lazy { Calendar.getInstance() } + private val realPaths = ArrayList() //真实图片路径 + private lateinit var imageAdapter: EditableImageAdapter + + var isReadMarker = false + var isInstallMarker = false + } + + /**探测标识器对话框******************************************************************************/ + inner class SearchMarkerDialog(context: Context) : Dialog(context) { + + private val binding: DialogSearchMarkerBinding by binding() + private val decimal by lazy { DecimalFormat("0.0") } + private val degreeCache by lazy { HashMap() } + private var isPlaying = false + private var markerId = "" + private lateinit var searchMarkerTimer: Timer + private lateinit var signalTask: TimerTask + private lateinit var energyTask: TimerTask + private lateinit var countDownTimer: CountDownTimer + + var isDetectMarker = false + var taskBean: TaskBean? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + this.initDialogLayoutParams(1f) + binding.depthButton.setOnClickListener { + signalTask.cancel() + energyTask.cancel() + searchMarkerTimer.cancel() + + out.write('3'.code) +// val result = DataBaseManager.get.queryLabelById(markerId) +// if (result.isNotEmpty()) { +// val tag = when (result.first().identifierType) { +// "EM30" -> '7' +// "EM50" -> '8' +// "EM14" -> '9' +// else -> '1' +// } +// if (tag == '1') { +// "此标识器无法读取埋深!".show(context) +// } else { +// // 发送读取标识器埋设深度指令 +// LoadingDialogHub.show(this@MainActivity, "正在测距,请稍后...") +// out.write(tag.code) +// out.flush() +// countDownTimer = object : CountDownTimer(15 * 1000, 1000) { +// override fun onTick(millisUntilFinished: Long) { +// +// } +// +// override fun onFinish() { +// LoadingDialogHub.dismiss() +// "探测此标识器深度超时,请重试".show(context) +// initTimer() +// } +// } +// countDownTimer.start() +// } +// } else { +// "标识器未安装,安装成功后才可读取埋深!".show(context) +// } + } + + binding.markerInfoButton.setOnClickListener { + //查库 + val result = DataBaseManager.get.queryLabelById(markerId) + if (result.isNotEmpty()) { +// context.navigatePageTo(result.first().toJson()) + } else { +// context.navigatePageTo(markerId) + } + } + } + + override fun onStart() { + super.onStart() + //调高串口电位 + gpioManager.setGpioHigh("18") + + initTimer() + + isDetectMarker = true + + //角度 + degreeCache["lastDegree"] = 0f + } + + fun bindingValue(hex: String) { + if (hex.startsWith("4E")) { + try { + //4E转为String为N,代表能量值 + //用能量值转动表盘 + val energyResponse = hex.take(10).hexToString() + val energy = energyResponse.substring(1).toInt() + if (energy >= 4000) { + isPlaying = if (!isPlaying) { + soundPool.play(fastSoundResourceId, 1f, 1f, 0, 0, 1f) + true + } else { + soundPool.pause(fastSoundResourceId) + false + } + } else { + isPlaying = if (!isPlaying) { + soundPool.play(slowSoundResourceId, 1f, 1f, 0, 0, 1f) + true + } else { + soundPool.pause(slowSoundResourceId) + false + } + } + + binding.resultTextView.text = "信号能量值:${energyResponse}" + + //转换为转动的角度 + val degree = (energy.toFloat() / (50 * 100)) * 180 + binding.energyValueView.text = decimal.format(degree) + + degreeCache["lastDegree"]?.apply { + val animation = RotateAnimation( + this, degree, + Animation.RELATIVE_TO_SELF, 0.5f, + Animation.RELATIVE_TO_SELF, 0.5f + ) + animation.duration = 0 + animation.fillAfter = true + binding.needleView.startAnimation(animation) + } + + //保存旋转后的角度 + degreeCache["lastDegree"] = degree + + if (energy <= 700) {//18° + binding.energyTipsView.text = "标识器信号较弱,可能距离较远" + binding.energyTipsView.setTextColor(Color.parseColor("#8D1717")) + binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_red) + + binding.depthButton.isEnabled = false + binding.depthButton.setTextColor(Color.parseColor("#CCCCCC")) + binding.depthButton.setBackgroundResource(R.mipmap.left_button_disable) + binding.markerInfoButton.isEnabled = false + binding.markerInfoButton.setTextColor(Color.parseColor("#CCCCCC")) + binding.markerInfoButton.setBackgroundResource(R.mipmap.right_button_disable) + + binding.searchResultView.text = "未检测到标识器" + binding.searchResultView.setTextColor(Color.parseColor("#8D1717")) + binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_red) + } else if (energy >= 4100) {//148° + binding.energyTipsView.text = "标识器信号极强,可能在正下方" + binding.energyTipsView.setTextColor(Color.parseColor("#428d00")) + binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_green) + } else {//[18°,148°] + binding.energyTipsView.text = "已靠近标识器,请继续移动位置" + binding.energyTipsView.setTextColor(Color.parseColor("#8C5700")) + binding.energyTipsView.setBackgroundResource(R.mipmap.bg_large_text_yellow) + } + } catch (e: NumberFormatException) { + e.printStackTrace() + } + } else if (hex.startsWith("53")) { + LoadingDialogHub.dismiss() + countDownTimer.cancel() + try { + val depthResponse = hex.take(10).hexToString() + val depth = depthResponse.drop(2).toInt() + AlertMessageDialog.Builder().setContext(context).setTitle("温馨提示") + .setMessage("标识器埋深:${depth}厘米").setPositiveButton("知道了") + .setOnDialogButtonClickListener(object : + AlertMessageDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + initTimer() + } + }).build().show() + } catch (e: NumberFormatException) { + e.printStackTrace() + } + } else { + val id = hex.take(20).hexToString() + if (id.isNumber()) { + markerId = id + + binding.depthButton.isEnabled = true + binding.depthButton.setTextColor(Color.WHITE) + binding.depthButton.setBackgroundResource(R.mipmap.left_button_enable) + binding.markerInfoButton.isEnabled = true + binding.markerInfoButton.setTextColor(Color.WHITE) + binding.markerInfoButton.setBackgroundResource(R.mipmap.right_button_enable) + + binding.searchResultView.text = "已检测到标识器" + binding.searchResultView.setTextColor(Color.parseColor("#428d00")) + binding.searchResultView.setBackgroundResource(R.mipmap.bg_small_text_green) + + //自动上传标识器 +// taskBean = DataBaseManager.get.queryTaskLabelByIdAndState(markerId, "未开始") +// taskBean?.apply { +// /** +// * 此taskCode是 [com.casic.detector.model.TaskModel.MessageModel.TaskDetailInfosModel] 里面的主键,也就是这个标签在数据库里面的主键 +// * */ +// taskViewModel.uploadMarker(taskCode) +// } + } + } + } + + private fun initTimer() { + searchMarkerTimer = Timer() + + signalTask = object : TimerTask() { + override fun run() { + out.write('2'.code) + out.flush() + } + } + + energyTask = object : TimerTask() { + override fun run() { + out.write('6'.code) + out.flush() + } + } + + //错开信号和能量定时器 + searchMarkerTimer.schedule(signalTask, 0, 201) + searchMarkerTimer.schedule(energyTask, 0, 251) + } + + override fun dismiss() { + signalTask.cancel() + energyTask.cancel() + searchMarkerTimer.cancel() + //降低串口电位 + gpioManager.setGpioLow("18") + isDetectMarker = false + soundPool.autoPause() + super.dismiss() + } } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt b/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt index 6a00429..cbd6137 100644 --- a/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt +++ b/app/src/main/java/com/casic/electric/detector/view/VersionControlActivity.kt @@ -13,18 +13,16 @@ import com.casic.electric.detector.R import com.casic.electric.detector.databinding.ActivityVersionControlBinding import com.casic.electric.detector.extensions.appendDownloadUrl -import com.casic.electric.detector.extensions.initLayoutImmersionBar +import com.casic.electric.detector.extensions.initImmersionBar import com.casic.electric.detector.utils.FileType -import com.casic.electric.detector.utils.LoadingDialogHub import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.vm.VersionViewModel -import com.gyf.immersionbar.ImmersionBar import com.pengxh.kt.lite.base.KotlinBaseActivity -import com.pengxh.kt.lite.callback.OnDownloadListener import com.pengxh.kt.lite.extensions.createDownloadFileDir -import com.pengxh.kt.lite.extensions.downloadFile import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.FileDownloadManager +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.LoadingDialogHub import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import java.io.File @@ -90,8 +88,7 @@ } override fun setupTopBarLayout() { - ImmersionBar.with(this).statusBarDarkFont(true).init() - initLayoutImmersionBar(binding.rootView) + binding.rootView.initImmersionBar(this, true, R.color.white) binding.titleInclude.titleView.visibility = View.GONE } @@ -108,22 +105,26 @@ val downloadPath = url!!.appendDownloadUrl(FileType.APK) Log.d(kTag, "downloadApk => $downloadPath") //开始下载 - downloadPath.downloadFile(createDownloadFileDir().toString(), object : OnDownloadListener { - override fun onDownloadStart(totalBytes: Long) { - progressDialog.max = totalBytes.toInt() - } + FileDownloadManager.Builder() + .setDownloadFileSource(downloadPath) + .setFileSuffix("apk") + .setFileSaveDirectory(createDownloadFileDir()) + .setOnFileDownloadListener(object : FileDownloadManager.OnFileDownloadListener { + override fun onDownloadEnd(file: File) { + progressDialog.dismiss() + progressDialog.progress = 0 + //安装APK + installApk(file) + } - override fun onProgressChanged(currentBytes: Long) { - progressDialog.progress = currentBytes.toInt() - } + override fun onFailure(throwable: Throwable) { - override fun onDownloadEnd(file: File?) { - progressDialog.dismiss() - progressDialog.progress = 0 - //安装APK - installApk(file) - } - }) + } + + override fun onProgressChanged(progress: Int) { + progressDialog.progress = progress + } + }).build().start() } private fun installApk(apkPackage: File?) { diff --git a/app/src/main/java/com/casic/electric/detector/vm/TaskViewModel.kt b/app/src/main/java/com/casic/electric/detector/vm/TaskViewModel.kt index 476a5f0..4b0bed6 100644 --- a/app/src/main/java/com/casic/electric/detector/vm/TaskViewModel.kt +++ b/app/src/main/java/com/casic/electric/detector/vm/TaskViewModel.kt @@ -2,125 +2,156 @@ import androidx.lifecycle.MutableLiveData import com.casic.electric.detector.base.BaseApplication -import com.casic.electric.detector.extensions.convertChinese -import com.casic.electric.detector.extensions.separateResponseState -import com.casic.electric.detector.extensions.toErrorMessage +import com.casic.electric.detector.extensions.getResponseMessage +import com.casic.electric.detector.extensions.getResponseState import com.casic.electric.detector.model.MarkerFileModel import com.casic.electric.detector.retrofit.RetrofitServiceManager import com.casic.electric.detector.utils.LabelDataClass +import com.casic.electric.detector.utils.LocaleConstant import com.casic.electric.detector.utils.SmallLabelDataClass import com.google.gson.Gson +import com.google.gson.JsonParser import com.google.gson.reflect.TypeToken +import com.pengxh.kt.lite.base.BaseViewModel import com.pengxh.kt.lite.extensions.launch import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState +import com.pengxh.kt.lite.utils.SaveKeyValues class TaskViewModel : BaseViewModel() { private val gson by lazy { Gson() } val markerFileResult = MutableLiveData() -// val taskResult = MutableLiveData() + + // val taskResult = MutableLiveData() + val freeTaskResult = MutableLiveData() + val uploadTaskMarkerResult = MutableLiveData() + + fun createFreeTask(patrollerId: String, description: String) = launch({ + val response = RetrofitServiceManager.createFreeTask(patrollerId, description) + if (response.getResponseState()) { + val element = JsonParser.parseString(response) + val jsonObject = element.asJsonObject + freeTaskResult.value = jsonObject.get("taskId").asInt.toString() + } else { + response.getResponseMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) + + fun uploadTaskMarker(taskId: String, models: ArrayList) = launch({ + val response = RetrofitServiceManager.uploadTaskMarker(taskId, models) + if (response.getResponseState()) { + val element = JsonParser.parseString(response) + val jsonObject = element.asJsonObject + uploadTaskMarkerResult.value = jsonObject.get("success").asString + } else { + response.getResponseMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) fun getMarkerFile(userId: String, companyId: String) = launch({ val response = RetrofitServiceManager.getMarkerFile(userId, companyId) - if (response.separateResponseState()) { + if (response.getResponseState()) { markerFileResult.value = gson.fromJson( response, object : TypeToken() {}.type ) } else { - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { - it.convertChinese().show(BaseApplication.get()) + it.printStackTrace() }) -// fun getTask(userName: String) = launch({ -// val response = RetrofitServiceManager.getTask(userName) -// if (response.separateResponseState()) { + fun getTask(userName: String) = launch({ + val response = RetrofitServiceManager.getTask(userName) + if (response.getResponseState()) { // taskResult.value = gson.fromJson( // response, object : TypeToken() {}.type // ) -// } else { -// response.toErrorMessage().show(BaseApplication.get()) -// } -// }, { -// it.convertChinese().show(BaseApplication.get()) -// }) + } else { + response.getResponseMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + }) fun installLabel(labelData: LabelDataClass) = launch({ loadState.value = LoadState.Loading val response = RetrofitServiceManager.installLabel(labelData) - if (response.separateResponseState()) { + if (response.getResponseState()) { loadState.value = LoadState.Success } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { + it.printStackTrace() loadState.value = LoadState.Fail - it.convertChinese().show(BaseApplication.get()) }) fun installSmallLabel(labelData: SmallLabelDataClass) = launch({ loadState.value = LoadState.Loading val response = RetrofitServiceManager.installSmallLabel(labelData) - if (response.separateResponseState()) { + if (response.getResponseState()) { loadState.value = LoadState.Success } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { + it.printStackTrace() loadState.value = LoadState.Fail - it.convertChinese().show(BaseApplication.get()) }) -// fun uploadTask(userId: String, taskId: String?, state: String) = launch({ -// loadState.value = LoadState.Loading -// val response = RetrofitServiceManager.uploadTask(userId, taskId, state) -// if (response.separateResponseState()) { -// loadState.value = LoadState.Success -// if (state == "2") { -// "工单${taskId}已提交!".show(BaseApplication.get()) -// //删除本地数据库 + fun uploadTask(userId: String, taskId: String?, state: String) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.uploadTask(userId, taskId, state) + if (response.getResponseState()) { + loadState.value = LoadState.Success + if (state == "2") { + "工单${taskId}已提交!".show(BaseApplication.get()) + //删除本地数据库 // DataBaseManager.get.deleteTaskById(taskId) -// SaveKeyValues.putValue(LocaleConstant.TASK_ID, "") -// } -// } else { -// loadState.value = LoadState.Fail -// response.toErrorMessage().show(BaseApplication.get()) -// } -// }, { -// loadState.value = LoadState.Fail -// it.convertChinese().show(BaseApplication.get()) -// }) + SaveKeyValues.putValue(LocaleConstant.TASK_ID, "") + } + } else { + loadState.value = LoadState.Fail + response.getResponseMessage().show(BaseApplication.get()) + } + }, { + it.printStackTrace() + loadState.value = LoadState.Fail + }) fun uploadEvent(taskId: String, event: String, realPaths: ArrayList) = launch({ loadState.value = LoadState.Loading val response = RetrofitServiceManager.uploadEvent(taskId, event, realPaths) - if (response.separateResponseState()) { + if (response.getResponseState()) { loadState.value = LoadState.Success } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { + it.printStackTrace() loadState.value = LoadState.Fail - it.convertChinese().show(BaseApplication.get()) }) - fun uploadMarker(userName: String, taskDetailId: String) = launch({ + fun uploadMarker(taskDetailId: String) = launch({ loadState.value = LoadState.Loading - val response = RetrofitServiceManager.uploadMarker(userName, taskDetailId) - if (response.separateResponseState()) { + val response = RetrofitServiceManager.uploadMarker(taskDetailId) + if (response.getResponseState()) { loadState.value = LoadState.Success } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { + it.printStackTrace() loadState.value = LoadState.Fail - it.convertChinese().show(BaseApplication.get()) }) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/electric/detector/vm/UserViewModel.kt b/app/src/main/java/com/casic/electric/detector/vm/UserViewModel.kt index e4a7b4e..ee6099b 100644 --- a/app/src/main/java/com/casic/electric/detector/vm/UserViewModel.kt +++ b/app/src/main/java/com/casic/electric/detector/vm/UserViewModel.kt @@ -2,17 +2,17 @@ import androidx.lifecycle.MutableLiveData import com.casic.electric.detector.base.BaseApplication -import com.casic.electric.detector.extensions.separateResponseState -import com.casic.electric.detector.extensions.toErrorMessage +import com.casic.electric.detector.extensions.getResponseMessage +import com.casic.electric.detector.extensions.getResponseState import com.casic.electric.detector.model.LoginResultModel import com.casic.electric.detector.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +import com.pengxh.kt.lite.base.BaseViewModel import com.pengxh.kt.lite.extensions.isNetworkConnected import com.pengxh.kt.lite.extensions.launch import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState /** * 用户相关 VM @@ -25,14 +25,14 @@ fun login(account: String, password: String) = launch({ loadState.value = LoadState.Loading val response = RetrofitServiceManager.login(account, password) - if (response.separateResponseState()) { + if (response.getResponseState()) { loadState.value = LoadState.Success loginResult.value = gson.fromJson( response, object : TypeToken() {}.type ) } else { loadState.value = LoadState.Fail - response.toErrorMessage().show(BaseApplication.get()) + response.getResponseMessage().show(BaseApplication.get()) } }, { loadState.value = LoadState.Fail diff --git a/app/src/main/java/com/casic/electric/detector/vm/VersionViewModel.kt b/app/src/main/java/com/casic/electric/detector/vm/VersionViewModel.kt index 6caf065..b488b5b 100644 --- a/app/src/main/java/com/casic/electric/detector/vm/VersionViewModel.kt +++ b/app/src/main/java/com/casic/electric/detector/vm/VersionViewModel.kt @@ -7,10 +7,10 @@ import com.casic.electric.detector.retrofit.RetrofitServiceManager import com.google.gson.Gson import com.google.gson.reflect.TypeToken +import com.pengxh.kt.lite.base.BaseViewModel import com.pengxh.kt.lite.extensions.launch import com.pengxh.kt.lite.extensions.show -import com.pengxh.kt.lite.vm.BaseViewModel -import com.pengxh.kt.lite.vm.LoadState +import com.pengxh.kt.lite.utils.LoadState class VersionViewModel : BaseViewModel() { private val gson by lazy { Gson() } diff --git a/app/src/main/res/layout/activity_big_image.xml b/app/src/main/res/layout/activity_big_image.xml index 9d060f4..228c2c4 100644 --- a/app/src/main/res/layout/activity_big_image.xml +++ b/app/src/main/res/layout/activity_big_image.xml @@ -1,5 +1,6 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +