增加终端反馈

This commit is contained in:
2025-11-18 16:29:38 +08:00
parent f8eeb83c6f
commit 79d14ca300
4 changed files with 146 additions and 80 deletions
@@ -6,18 +6,14 @@ import android.graphics.Color
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.provider.Settings
import android.util.Log import android.util.Log
import android.util.SparseArray
import android.util.SparseIntArray import android.util.SparseIntArray
import android.view.View
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.DefaultItemAnimator import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import com.chad.library.adapter4.util.setOnDebouncedItemClick
import com.shuwei.intelligent.shelves.adapter.ShelfAdapter import com.shuwei.intelligent.shelves.adapter.ShelfAdapter
import com.shuwei.intelligent.shelves.base.BaseActivity import com.shuwei.intelligent.shelves.base.BaseActivity
import com.shuwei.intelligent.shelves.databinding.ActivityHomeBinding import com.shuwei.intelligent.shelves.databinding.ActivityHomeBinding
@@ -33,7 +29,6 @@ import com.shuwei.intelligent.shelves.net.RespData
import com.shuwei.intelligent.shelves.net.UiState import com.shuwei.intelligent.shelves.net.UiState
import com.shuwei.intelligent.shelves.net.apiService import com.shuwei.intelligent.shelves.net.apiService
import com.shuwei.intelligent.shelves.serial.SerialPortManager import com.shuwei.intelligent.shelves.serial.SerialPortManager
import com.shuwei.intelligent.shelves.task.SyncTask
import com.shuwei.intelligent.shelves.task.TaskManager import com.shuwei.intelligent.shelves.task.TaskManager
import com.shuwei.intelligent.shelves.utils.binaryToHex import com.shuwei.intelligent.shelves.utils.binaryToHex
import com.shuwei.intelligent.shelves.utils.ext.gone import com.shuwei.intelligent.shelves.utils.ext.gone
@@ -43,9 +38,7 @@ import com.shuwei.intelligent.shelves.utils.ext.visible
import com.shuwei.intelligent.shelves.utils.f2C import com.shuwei.intelligent.shelves.utils.f2C
import com.shuwei.intelligent.shelves.utils.hexToBinary import com.shuwei.intelligent.shelves.utils.hexToBinary
import com.shuwei.intelligent.shelves.utils.hexToDec import com.shuwei.intelligent.shelves.utils.hexToDec
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode import org.greenrobot.eventbus.ThreadMode
@@ -76,6 +69,7 @@ class HomeActivity : BaseActivity() {
//const val TEMPERATURE_CMD = "${HEADER}1001${FOOTER}" //const val TEMPERATURE_CMD = "${HEADER}1001${FOOTER}"
const val DEVICE_INFO_CMD = "${HEADER}0301000000000000000000000000${FOOTER}" const val DEVICE_INFO_CMD = "${HEADER}0301000000000000000000000000${FOOTER}"
//const val START_CMD= "${HEADER}0F01360000${FOOTER}" //const val START_CMD= "${HEADER}0F01360000${FOOTER}"
//const val START_CMD= "${HEADER}0F01050020${FOOTER}" //const val START_CMD= "${HEADER}0F01050020${FOOTER}"
const val ACTIVE_CMD = const val ACTIVE_CMD =
@@ -115,22 +109,22 @@ class HomeActivity : BaseActivity() {
updateLeftStatus("-°C / -%") updateLeftStatus("-°C / -%")
initRecyclerView() initRecyclerView()
lifecycleScope.launch {
val openState = SerialPortManager.open() val openState = SerialPortManager.open()
Log.d(TAG, "onCreate: openState=$openState") Log.d(TAG, "onCreate: openState=$openState")
if (openState) { if (openState) {
SerialPortManager.startReceive { data -> SerialPortManager.startReceive { data ->
runOnUiThread { runOnUiThread {
// 更新UI显示接收数据 // 更新UI显示接收数据
try {
receiveSerialPortData(data) receiveSerialPortData(data)
} catch (e: Exception) {
e.printStackTrace()
}
} }
} }
SerialPortManager.send(ACTIVE_CMD)
//SerialPortManager.send(DEVICE_INFO_CMD) //SerialPortManager.send(DEVICE_INFO_CMD)
} }
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.CREATED) { repeatOnLifecycle(Lifecycle.State.CREATED) {
launch { launch {
viewModel.getAccessTokenUiState.collect { state -> viewModel.getAccessTokenUiState.collect { state ->
@@ -253,6 +247,16 @@ class HomeActivity : BaseActivity() {
loadEmptyView() loadEmptyView()
} }
/**
* 终端id
*/
private var terminalId: String = ""
/**
* 固件版本
*/
private var terminalVersion: String = ""
private val serialReader by lazy { StringBuilder() } private val serialReader by lazy { StringBuilder() }
private fun receiveSerialPortData(srcData: String) { private fun receiveSerialPortData(srcData: String) {
@@ -280,38 +284,86 @@ class HomeActivity : BaseActivity() {
val cmd = data.substring(HEADER.length, HEADER.length + 4) val cmd = data.substring(HEADER.length, HEADER.length + 4)
when (cmd) { when (cmd) {
"0001" -> { "0001" -> {
//终端发起激活指令,拿到固定数据体(终端ID-15字节、固件版本-5字节、命令次数-1字节)
val reqBody = data.substring(HEADER.length + cmd.length, data.length - HEADER.length)
if (reqBody.length == 64) {
terminalId = reqBody.substring(2, 32)
terminalVersion = reqBody.substring(32, 42)
Log.d(TAG, "receiveSerialPortData:收到[激活]${cmd.substring(0,2)}指令:${data},终端id:${terminalId},固件版本:${terminalVersion},发送激活命令:${ACTIVE_CMD}")
SerialPortManager.send(ACTIVE_CMD)
} else {
runOnUiThread {
toast("收到终端激活指令错误")
}
SerialPortManager.send(ACTIVE_CMD)
}
} }
"0101" -> { "0101","8101" -> {
//心跳-01 //心跳0102${p1}${p2}${version}
Log.d(TAG, "receiveSerialPortData:心跳01: $data") //心跳81(终端发起,当终端发送此命令时需要服务端存储串口屏显示信息)
val respCmd = "${HEADER}01020106${terminalVersion}${FOOTER}"
Log.d(TAG, "receiveSerialPortData:收到[心跳]${cmd.substring(0,2)}指令:${data},发送应答指令:${respCmd}")
SerialPortManager.send(respCmd)
heartBeat(data) heartBeat(data)
} }
// "8101" -> {
// //心跳-81 "0202" -> {
// Log.d(TAG, "receiveSerialPortData:心跳08: $data") //开关锁反馈020200${deviceId}${version}
// heartBeat(data) val respCmd = "${HEADER}020200${terminalId}${terminalVersion}${FOOTER}"
// } Log.d(TAG, "receiveSerialPortData:收到[开锁]${cmd.substring(0,2)}指令:${data},发送应答指令:${respCmd}")
// "0202" -> { SerialPortManager.send(respCmd)
// //开关锁反馈 //lockFeedback(data)
// lockFeedback(data) }
// }
"0302" -> { "0302" -> {
//获取设备状态 //获取设备状态
getDeviceInfo(data) getDeviceInfo(data)
} }
"0501" -> {
//卡号上发
val respCmd = "${HEADER}050203${FOOTER}"
Log.d(TAG, "receiveSerialPortData:收到[卡号上发]${cmd.substring(0,2)}指令:${data},发送应答指令:${respCmd}")
SerialPortManager.send(respCmd)
}
"0B01" -> {
//操作记录上传
val respCmd = "${HEADER}0B0203${FOOTER}"
Log.d(TAG, "receiveSerialPortData:收到[操作记录上传]${cmd.substring(0,2)}指令:${data},发送应答指令:${respCmd}")
SerialPortManager.send(respCmd)
}
"0C01" -> {
//对时
val timeLong = System.currentTimeMillis() / 1000 + (8 * 3600)
val timeStr = "0000000" + String.format("%X", timeLong)
val time = timeStr.substring(timeStr.length - 8).chunked(2).reversed().joinToString("")
val respCmd = "${HEADER}0B02${time}${FOOTER}"
Log.d(TAG, "receiveSerialPortData:收到[对时]${cmd.substring(0,2)}指令:${data},发送应答指令:${respCmd}")
SerialPortManager.send(respCmd)
}
"0E01" -> {
//终端位置上报
val respCmd = "${HEADER}0E0200${FOOTER}"
Log.d(TAG, "receiveSerialPortData:收到[终端位置上报]${cmd.substring(0,2)}指令:${data},发送应答指令:${respCmd}")
SerialPortManager.send(respCmd)
}
"1001" -> { "1001" -> {
Log.d(TAG, "receiveSerialPortData,温控信息上报数据:${data}") //温控信息上报
runOnUiThread { toast("温控信息上报数据:${data}") } val respCmd = "${HEADER}100200${FOOTER}"
} Log.d(TAG, "receiveSerialPortData:收到[温控信息上报]${cmd.substring(0,2)}指令:${data},发送应答指令:${respCmd}")
"1002" -> { SerialPortManager.send(respCmd)
Log.d(TAG, "receiveSerialPortData,温控信息上报1002数据:${data}")
}
"0F02" -> {
Log.d(TAG, "receiveSerialPortData,温控信息应答数据:${data}")
} }
//"1002" -> {
// Log.d(TAG, "receiveSerialPortData,温控信息上报1002数据:${data}")
//}
//"0F02" -> {
// Log.d(TAG, "receiveSerialPortData,温控信息应答数据:${data}")
//}
else -> {} else -> {}
} }
} }
@@ -328,17 +380,13 @@ class HomeActivity : BaseActivity() {
val lockOneState = data.substring(HEADER.length + 4, HEADER.length + 6) val lockOneState = data.substring(HEADER.length + 4, HEADER.length + 6)
if (lockOneState == "00") { if (lockOneState == "00") {
//锁1关 //锁1关
lifecycleScope.launch {
SerialPortManager.send("${HEADER}0202${lockNo}${FOOTER}") SerialPortManager.send("${HEADER}0202${lockNo}${FOOTER}")
} }
}
val lockTwoState = data.substring(HEADER.length + 6, HEADER.length + 8) val lockTwoState = data.substring(HEADER.length + 6, HEADER.length + 8)
if (lockTwoState == "00") { if (lockTwoState == "00") {
//锁2关 //锁2关
lifecycleScope.launch {
SerialPortManager.send("${HEADER}0202${lockNo}${FOOTER}") SerialPortManager.send("${HEADER}0202${lockNo}${FOOTER}")
} }
}
}.onFailure { }.onFailure {
it.printStackTrace() it.printStackTrace()
} }
@@ -442,6 +490,20 @@ class HomeActivity : BaseActivity() {
end = temperatureStartIndex, end = temperatureStartIndex,
data = data data = data
) )
if (terminalId.isBlank() || terminalVersion.isBlank()) {
try {
val fixDataBodyStartIndex = temperatureEndIndex + 1
val fixDataBody = data.substring(fixDataBodyStartIndex)
if (fixDataBody.length == 62) {
terminalId = fixDataBody.substring(0, 30)
terminalVersion = fixDataBody.substring(30, 40)
Log.d(TAG, "receiveSerialPortData:从设备状态获取数据,终端id:${terminalId},固件版本:${terminalVersion}")
}
} catch (e: Exception) {
e.printStackTrace()
}
}
} }
override fun onDestroy() { override fun onDestroy() {
@@ -487,7 +549,7 @@ class HomeActivity : BaseActivity() {
try { try {
val submitList = list.sortedBy { item-> item.deviceNo } val submitList = list.sortedBy { item -> item.deviceNo }
val body = ShelfBody().also { body -> val body = ShelfBody().also { body ->
body.deviceId = App.deviceId ?: "" body.deviceId = App.deviceId ?: ""
body.canteenId = App.canteenId body.canteenId = App.canteenId
@@ -577,7 +639,7 @@ class HomeActivity : BaseActivity() {
goodsId = "" goodsId = ""
goodsName = null goodsName = null
weight = 0.0 weight = 0.0
weightBak = if (event.weight <= 0.0 ) 0.0 else -1 * event.weight.toDouble() weightBak = if (event.weight <= 0.0) 0.0 else -1 * event.weight.toDouble()
createTime = null createTime = null
overdueDay = null overdueDay = null
} }
@@ -84,7 +84,7 @@ open class BaseActivity : AppCompatActivity() {
} }
fun setBackground() { fun setBackground() {
binding.root.setBackgroundColor(ContextCompat.getColor(this,R.color.bg_page)) binding.root.setBackgroundColor(ContextCompat.getColor(this, R.color.bg_page))
} }
override fun setContentView(view: View?) { override fun setContentView(view: View?) {
@@ -115,7 +115,7 @@ open class BaseActivity : AppCompatActivity() {
override fun onUserInteraction() { override fun onUserInteraction() {
super.onUserInteraction() super.onUserInteraction()
//开灯 //开灯
if(System.currentTimeMillis() - lastTouchTime >= TIME_OUT) { if (System.currentTimeMillis() - lastTouchTime >= TIME_OUT) {
this.switchLight(true) this.switchLight(true)
} }
// 重置定时器 // 重置定时器
@@ -140,12 +140,10 @@ open class BaseActivity : AppCompatActivity() {
fun switchLight(isOpen: Boolean) { fun switchLight(isOpen: Boolean) {
val tag = binding.tvLeftStatus.tag?.toString()?.toBoolean() ?: true val tag = binding.tvLeftStatus.tag?.toString()?.toBoolean() ?: true
if(tag == isOpen) { if (tag == isOpen) {
return return
} }
lifecycleScope.launch {
SerialPortManager.send(if (isOpen) LIGHT_OPEN else LIGHT_CLOSE) SerialPortManager.send(if (isOpen) LIGHT_OPEN else LIGHT_CLOSE)
}
binding.tvLeftStatus.tag = isOpen binding.tvLeftStatus.tag = isOpen
} }
@@ -1,6 +1,7 @@
package com.shuwei.intelligent.shelves.serial package com.shuwei.intelligent.shelves.serial
import android.annotation.SuppressLint import android.annotation.SuppressLint
import androidx.lifecycle.lifecycleScope
import com.shuwei.intelligent.shelves.utils.hexToBytes import com.shuwei.intelligent.shelves.utils.hexToBytes
import com.shuwei.intelligent.shelves.utils.toHexString2 import com.shuwei.intelligent.shelves.utils.toHexString2
import io.github.jeadyx.jserialport.AndroidSerialPort import io.github.jeadyx.jserialport.AndroidSerialPort
@@ -15,11 +16,13 @@ object SerialPortManager {
private const val portName: String = "/dev/ttyS1" private const val portName: String = "/dev/ttyS1"
private const val baudRate: Int = 115200 private const val baudRate: Int = 115200
private var serialPort: AndroidSerialPort? = null private var serialPort: AndroidSerialPort? = null
// private var serialPort: SerialPort? = null
// private var serialPort: SerialPort? = null
private val scope = CoroutineScope(Dispatchers.IO) private val scope = CoroutineScope(Dispatchers.IO)
// 打开串口 // 打开串口
suspend fun open(): Boolean { fun open(): Boolean {
lifecycleScope.launch {
return try { return try {
serialPort = SerialPortFactory.create().apply { serialPort = SerialPortFactory.create().apply {
open( open(
@@ -36,9 +39,11 @@ object SerialPortManager {
false false
} }
} }
}
// 发送数据 // 发送数据
suspend fun send(data: String): Boolean { fun send(data: String): Boolean {
lifecycleScope.launch {
return try { return try {
serialPort?.write(data.hexToBytes()) serialPort?.write(data.hexToBytes())
true true
@@ -47,6 +52,7 @@ object SerialPortManager {
false false
} }
} }
}
// 启动接收协程 // 启动接收协程
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
@@ -14,7 +14,7 @@ class SyncDeviceTask(appContext: Context, workerParams: WorkerParameters) :
private const val TAG = "SyncDeviceTask" private const val TAG = "SyncDeviceTask"
} }
override suspend fun doWork(): Result { override fun doWork(): Result {
return try { return try {
// 执行后台任务逻辑 // 执行后台任务逻辑
Log.d(TAG, "doWork: ----------SyncDeviceTask----------") Log.d(TAG, "doWork: ----------SyncDeviceTask----------")