From 096499cd658995d2d5ff5be3e6ad0279ded1d605 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=A9=AC=E5=A2=9E=E9=A3=9E?= <331023091@qq.com>
Date: Tue, 18 Nov 2025 18:49:46 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=B9=B6=E5=A2=9E=E5=8A=A0?=
=?UTF-8?q?=E6=97=A5=E5=BF=97?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/src/main/AndroidManifest.xml | 9 +-
.../shelves/{ => activity}/HomeActivity.kt | 181 +++++++++---------
.../shelves/{ => activity}/InitActivity.kt | 11 +-
.../shelves/activity/LogActivity.kt | 57 ++++++
.../shelves/{ => activity}/SettingActivity.kt | 9 +-
.../shelves/{ => activity}/ShelfActivity.kt | 19 +-
.../intelligent/shelves/adapter/LogAdapter.kt | 25 +++
.../intelligent/shelves/base/BaseActivity.kt | 33 +++-
.../shelves/serial/SerialPortManager.kt | 48 +++--
.../shelves/task/SyncDeviceTask.kt | 4 +-
.../intelligent/shelves/task/SyncTask.kt | 2 +-
.../intelligent/shelves/utils/BootReceiver.kt | 2 +-
.../intelligent/shelves/utils/FileLogger.kt | 109 +++++++++++
.../res/layout-sw600dp/activity_log_list.xml | 38 ++++
.../main/res/layout-sw600dp/list_item_log.xml | 26 +++
app/src/main/res/layout/activity_log_list.xml | 38 ++++
app/src/main/res/layout/list_item_log.xml | 26 +++
17 files changed, 482 insertions(+), 155 deletions(-)
rename app/src/main/java/com/shuwei/intelligent/shelves/{ => activity}/HomeActivity.kt (82%)
rename app/src/main/java/com/shuwei/intelligent/shelves/{ => activity}/InitActivity.kt (94%)
create mode 100644 app/src/main/java/com/shuwei/intelligent/shelves/activity/LogActivity.kt
rename app/src/main/java/com/shuwei/intelligent/shelves/{ => activity}/SettingActivity.kt (87%)
rename app/src/main/java/com/shuwei/intelligent/shelves/{ => activity}/ShelfActivity.kt (95%)
create mode 100644 app/src/main/java/com/shuwei/intelligent/shelves/adapter/LogAdapter.kt
create mode 100644 app/src/main/java/com/shuwei/intelligent/shelves/utils/FileLogger.kt
create mode 100644 app/src/main/res/layout-sw600dp/activity_log_list.xml
create mode 100644 app/src/main/res/layout-sw600dp/list_item_log.xml
create mode 100644 app/src/main/res/layout/activity_log_list.xml
create mode 100644 app/src/main/res/layout/list_item_log.xml
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index b762cfb..2de11d9 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -26,7 +26,7 @@
android:theme="@style/Theme.IntelligentShelves"
android:usesCleartextTraffic="true">
@@ -37,13 +37,14 @@
-
+
+
= mutableListOf()
val weightArray = SparseIntArray()
@@ -97,7 +99,6 @@ class HomeActivity : BaseActivity() {
private val viewModel: NetViewModel by viewModels()
-
@SuppressLint("NotifyDataSetChanged", "HardwareIds")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -109,22 +110,22 @@ class HomeActivity : BaseActivity() {
updateLeftStatus("-°C / -%")
initRecyclerView()
- val openState = SerialPortManager.open()
- Log.d(TAG, "onCreate: openState=$openState")
- if (openState) {
- SerialPortManager.startReceive { data ->
- runOnUiThread {
+ lifecycleScope.launch {
+ val openState = SerialPortManager.open()
+ log("onCreate: openState=$openState")
+ if (openState) {
+ SerialPortManager.startReceive { data ->
// 更新UI显示接收数据
- try {
- receiveSerialPortData(data)
- } catch (e: Exception) {
- e.printStackTrace()
+ lifecycleScope.launch {
+ try {
+ receiveSerialPortData(data)
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
}
}
+ //SerialPortManager.send(DEVICE_INFO_CMD)
}
- //SerialPortManager.send(DEVICE_INFO_CMD)
- }
- lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.CREATED) {
launch {
viewModel.getAccessTokenUiState.collect { state ->
@@ -152,7 +153,7 @@ class HomeActivity : BaseActivity() {
// var androidId = Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)
//// androidId = "d0e7a2d5f25c775c"
-// Log.d(TAG, "onCreate: androidId=${androidId}")
+// log("onCreate: androidId=${androidId}")
// if (androidId == "65e1012638f78260" || androidId == "40f89e91ee40611d") {
// androidId = "d0e7a2d5f25c775c"
// }
@@ -160,7 +161,7 @@ class HomeActivity : BaseActivity() {
// //"53babf69-0d2f-3875-a649-f2e12f80ad4c1"
//
// val swDpValue = resources?.configuration?.smallestScreenWidthDp
-// Log.d(TAG, "onCreate: swDpValue=$swDpValue")
+// log("onCreate: swDpValue=$swDpValue")
// viewModel.getAccessToken(App.deviceId)
@@ -200,7 +201,7 @@ class HomeActivity : BaseActivity() {
}
private fun getTokenSuccess(data: RespData<*>) {
- Log.d(TAG, "getTokenSuccess: $data")
+ log("getTokenSuccess: $data")
data.data?.let {
App.accessToken = it.toString()
//UIUtils.toast(it.toString())
@@ -259,8 +260,8 @@ class HomeActivity : BaseActivity() {
private val serialReader by lazy { StringBuilder() }
- private fun receiveSerialPortData(srcData: String) {
- Log.d(TAG, "receiveSerialPortData: $srcData")
+ private suspend fun receiveSerialPortData(srcData: String) {
+ log("receiveSerialPortData: $srcData")
var data = ""
if (srcData.startsWith(HEADER) && srcData.contains(FOOTER)) {
serialReader.clear()
@@ -277,7 +278,7 @@ class HomeActivity : BaseActivity() {
} else {
val endIndex = srcData.indexOf(FOOTER) + FOOTER.length
serialReader.append(srcData.substring(0, endIndex))
- Log.d(TAG, "receiveSerialPortData:serialReader: $serialReader")
+ log("receiveSerialPortData:serialReader: $serialReader")
data = serialReader.toString().replace(",", "")
}
@@ -289,30 +290,30 @@ class HomeActivity : BaseActivity() {
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)
+ log("receiveSerialPortData:收到[激活]${cmd.substring(0,2)}指令:${data},终端id:${terminalId},固件版本:${terminalVersion},发送激活命令:$ACTIVE_CMD")
+ sendCmd(ACTIVE_CMD)
} else {
runOnUiThread {
toast("收到终端激活指令错误")
}
- SerialPortManager.send(ACTIVE_CMD)
+ sendCmd(ACTIVE_CMD)
}
}
"0101","8101" -> {
//心跳0102${p1}${p2}${version}
//心跳81(终端发起,当终端发送此命令时需要服务端存储串口屏显示信息)
- val respCmd = "${HEADER}01020106${terminalVersion}${FOOTER}"
- Log.d(TAG, "receiveSerialPortData:收到[心跳]${cmd.substring(0,2)}指令:${data},发送应答指令:${respCmd}")
- SerialPortManager.send(respCmd)
+ val respCmd = "${HEADER}01020106${terminalVersion}$FOOTER"
+ log("receiveSerialPortData:收到[心跳]${cmd.substring(0,2)}指令:${data},发送应答指令:${respCmd}")
+ sendCmd(respCmd)
heartBeat(data)
}
"0202" -> {
//开关锁反馈020200${deviceId}${version}
- val respCmd = "${HEADER}020200${terminalId}${terminalVersion}${FOOTER}"
- Log.d(TAG, "receiveSerialPortData:收到[开锁]${cmd.substring(0,2)}指令:${data},发送应答指令:${respCmd}")
- SerialPortManager.send(respCmd)
+ val respCmd = "${HEADER}020200${terminalId}${terminalVersion}$FOOTER"
+ log("receiveSerialPortData:收到[开锁]${cmd.substring(0,2)}指令:${data},发送应答指令:${respCmd}")
+ sendCmd(respCmd)
//lockFeedback(data)
}
@@ -323,16 +324,16 @@ class HomeActivity : BaseActivity() {
"0501" -> {
//卡号上发
- val respCmd = "${HEADER}050203${FOOTER}"
- Log.d(TAG, "receiveSerialPortData:收到[卡号上发]${cmd.substring(0,2)}指令:${data},发送应答指令:${respCmd}")
- SerialPortManager.send(respCmd)
+ val respCmd = "${HEADER}050203$FOOTER"
+ log("receiveSerialPortData:收到[卡号上发]${cmd.substring(0,2)}指令:${data},发送应答指令:${respCmd}")
+ sendCmd(respCmd)
}
"0B01" -> {
//操作记录上传
- val respCmd = "${HEADER}0B0203${FOOTER}"
- Log.d(TAG, "receiveSerialPortData:收到[操作记录上传]${cmd.substring(0,2)}指令:${data},发送应答指令:${respCmd}")
- SerialPortManager.send(respCmd)
+ val respCmd = "${HEADER}0B0203$FOOTER"
+ log("receiveSerialPortData:收到[操作记录上传]${cmd.substring(0,2)}指令:${data},发送应答指令:${respCmd}")
+ sendCmd(respCmd)
}
"0C01" -> {
@@ -340,28 +341,28 @@ class HomeActivity : BaseActivity() {
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)
+ val respCmd = "${HEADER}0B02${time}$FOOTER"
+ log("receiveSerialPortData:收到[对时]${cmd.substring(0,2)}指令:${data},发送应答指令:${respCmd}")
+ sendCmd(respCmd)
}
"0E01" -> {
//终端位置上报
- val respCmd = "${HEADER}0E0200${FOOTER}"
- Log.d(TAG, "receiveSerialPortData:收到[终端位置上报]${cmd.substring(0,2)}指令:${data},发送应答指令:${respCmd}")
- SerialPortManager.send(respCmd)
+ val respCmd = "${HEADER}0E0200$FOOTER"
+ log("receiveSerialPortData:收到[终端位置上报]${cmd.substring(0,2)}指令:${data},发送应答指令:${respCmd}")
+ sendCmd(respCmd)
}
"1001" -> {
//温控信息上报
- val respCmd = "${HEADER}100200${FOOTER}"
- Log.d(TAG, "receiveSerialPortData:收到[温控信息上报]${cmd.substring(0,2)}指令:${data},发送应答指令:${respCmd}")
- SerialPortManager.send(respCmd)
+ val respCmd = "${HEADER}100200$FOOTER"
+ log("receiveSerialPortData:收到[温控信息上报]${cmd.substring(0,2)}指令:${data},发送应答指令:${respCmd}")
+ sendCmd(respCmd)
}
//"1002" -> {
- // Log.d(TAG, "receiveSerialPortData,温控信息上报1002数据:${data}")
+ // log("receiveSerialPortData,温控信息上报1002数据:${data}")
//}
//"0F02" -> {
- // Log.d(TAG, "receiveSerialPortData,温控信息应答数据:${data}")
+ // log("receiveSerialPortData,温控信息应答数据:${data}")
//}
else -> {}
@@ -370,27 +371,27 @@ class HomeActivity : BaseActivity() {
private var fixedDataBody = ""
- private fun lockFeedback(data: String) {
- runCatching {
- val fixedDataBodyEndIndex = data.length - FOOTER.length
- val fixedDataBodyStartIndex = HEADER.length + "0202".length + 42
- fixedDataBody = data.substring(fixedDataBodyStartIndex, fixedDataBodyEndIndex)
-
- val lockNo = if (list[shelfIndex].deviceNo in 1..5) "01" else "02"
- val lockOneState = data.substring(HEADER.length + 4, HEADER.length + 6)
- if (lockOneState == "00") {
- //锁1关
- SerialPortManager.send("${HEADER}0202${lockNo}${FOOTER}")
- }
- val lockTwoState = data.substring(HEADER.length + 6, HEADER.length + 8)
- if (lockTwoState == "00") {
- //锁2关
- SerialPortManager.send("${HEADER}0202${lockNo}${FOOTER}")
- }
- }.onFailure {
- it.printStackTrace()
- }
- }
+// private fun lockFeedback(data: String) {
+// runCatching {
+// val fixedDataBodyEndIndex = data.length - FOOTER.length
+// val fixedDataBodyStartIndex = HEADER.length + "0202".length + 42
+// fixedDataBody = data.substring(fixedDataBodyStartIndex, fixedDataBodyEndIndex)
+//
+// val lockNo = if (list[shelfIndex].deviceNo in 1..5) "01" else "02"
+// val lockOneState = data.substring(HEADER.length + 4, HEADER.length + 6)
+// if (lockOneState == "00") {
+// //锁1关
+// SerialPortManager.send("${HEADER}0202${lockNo}${FOOTER}")
+// }
+// val lockTwoState = data.substring(HEADER.length + 6, HEADER.length + 8)
+// if (lockTwoState == "00") {
+// //锁2关
+// SerialPortManager.send("${HEADER}0202${lockNo}${FOOTER}")
+// }
+// }.onFailure {
+// it.printStackTrace()
+// }
+// }
private fun heartBeat(data: String) {
runCatching {
@@ -450,7 +451,7 @@ class HomeActivity : BaseActivity() {
it.weight = realWeight.toDouble()
val pos = list.indexOf(it)
shelfAdapter.notifyItemChanged(pos)
- Log.d(TAG, "getWeightInfo: deviceNo=${it.deviceNo},realWeight=${realWeight}")
+ log("getWeightInfo: deviceNo=${it.deviceNo},realWeight=${realWeight}")
EventBus.getDefault().post(SendWeightEvent(it.deviceNo, realWeight))
}
}
@@ -464,10 +465,25 @@ class HomeActivity : BaseActivity() {
// intent.putExtra(ShelfActivity.SHELF_WEIGHT, weightArray[shelfIndex])
// LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
// }
+
+ val temperatureEndIndex = end
+ if (terminalId.isBlank() || terminalVersion.isBlank()) {
+ try {
+ val fixDataBodyStartIndex = temperatureEndIndex + 1
+ val fixDataBody = data.substring(fixDataBodyStartIndex, data.length- FOOTER.length)
+ if (fixDataBody.length == 42) {
+ terminalId = fixDataBody.substring(0, 30)
+ terminalVersion = fixDataBody.substring(30, 40)
+ log("receiveSerialPortData:从设备状态获取数据,终端id:${terminalId},固件版本:${terminalVersion}")
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ }
}
private fun getDeviceInfo(data: String) {
- Log.d(TAG, "getDeviceInfo: data=$data")
+ log("getDeviceInfo: data=$data")
val weightStartIndex = HEADER.length + 14
val temperatureStartIndex = weightStartIndex + 12 * 8
val temperatureEndIndex = temperatureStartIndex + 2
@@ -491,19 +507,6 @@ class HomeActivity : BaseActivity() {
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() {
diff --git a/app/src/main/java/com/shuwei/intelligent/shelves/InitActivity.kt b/app/src/main/java/com/shuwei/intelligent/shelves/activity/InitActivity.kt
similarity index 94%
rename from app/src/main/java/com/shuwei/intelligent/shelves/InitActivity.kt
rename to app/src/main/java/com/shuwei/intelligent/shelves/activity/InitActivity.kt
index 2c23000..66bac66 100644
--- a/app/src/main/java/com/shuwei/intelligent/shelves/InitActivity.kt
+++ b/app/src/main/java/com/shuwei/intelligent/shelves/activity/InitActivity.kt
@@ -1,14 +1,13 @@
-package com.shuwei.intelligent.shelves
+package com.shuwei.intelligent.shelves.activity
import android.annotation.SuppressLint
import android.os.Bundle
-import android.provider.Settings
import android.util.Log
import androidx.activity.viewModels
import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
+import com.shuwei.intelligent.shelves.App
import com.shuwei.intelligent.shelves.base.BaseActivity
import com.shuwei.intelligent.shelves.databinding.ActivityInitBinding
import com.shuwei.intelligent.shelves.model.DeviceConfigInfo
@@ -24,17 +23,13 @@ import com.shuwei.intelligent.shelves.utils.ext.startActivity
import com.shuwei.intelligent.shelves.utils.ext.toJsonString
import com.shuwei.intelligent.shelves.utils.ext.toObject
import com.shuwei.intelligent.shelves.utils.ext.toast
-import com.shuwei.intelligent.shelves.utils.ext.visible
import kotlinx.coroutines.delay
-import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.launch
import kotlin.collections.forEach
import kotlin.getValue
-import kotlin.jvm.java
import kotlin.ranges.downTo
import kotlin.text.isBlank
-import kotlin.to
class InitActivity : BaseActivity() {
companion object {
@@ -53,7 +48,7 @@ class InitActivity : BaseActivity() {
App.deviceId = AppUtil.getUDID( this)
- SpTool.put(SpTool.DEVICE_ID, App.deviceId)
+ SpTool.put(SpTool.DEVICE_ID, App.deviceId)
App.configUrl = UrlConfig.BASE_URL
App.canteenId = "0"
diff --git a/app/src/main/java/com/shuwei/intelligent/shelves/activity/LogActivity.kt b/app/src/main/java/com/shuwei/intelligent/shelves/activity/LogActivity.kt
new file mode 100644
index 0000000..3ba4541
--- /dev/null
+++ b/app/src/main/java/com/shuwei/intelligent/shelves/activity/LogActivity.kt
@@ -0,0 +1,57 @@
+package com.shuwei.intelligent.shelves.activity
+
+import android.os.Bundle
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.shuwei.intelligent.shelves.adapter.LogAdapter
+import com.shuwei.intelligent.shelves.base.BaseActivity
+import com.shuwei.intelligent.shelves.databinding.ActivityLogListBinding
+import com.shuwei.intelligent.shelves.utils.ext.startActivity
+
+class LogActivity : BaseActivity() {
+
+ companion object {
+ const val IS_LOG_DIR = "isLogDir"
+ const val LOG_DATE = "logDate"
+ }
+
+ private lateinit var binding:ActivityLogListBinding
+ private var isLogDir = false
+ private var logDate = ""
+ private val logList = mutableListOf()
+ private val logAdapter by lazy {
+ LogAdapter(logList).apply {
+ setOnItemClickListener { _, _, position ->
+ if (isLogDir.not()) {
+ return@setOnItemClickListener
+ }
+ startActivity {
+ putExtra(IS_LOG_DIR, false)
+ putExtra(LOG_DATE, logList[position])
+ }
+ }
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivityLogListBinding.inflate(layoutInflater)
+ setBackground()
+ setContentView(binding.root)
+ isLogDir = intent.getBooleanExtra(IS_LOG_DIR, false)
+ logDate = intent.getStringExtra(LOG_DATE) ?: ""
+ binding.ivBack.setOnClickListener { finish() }
+ binding.tvTitle.text = if (isLogDir) "全部日志" else logDate
+
+ if (isLogDir) {
+ logList.addAll(fileLogger.getLogFiles())
+ } else {
+ logList.addAll(fileLogger.readLogsByName(logDate))
+ }
+
+ binding.rvLogList.let {
+ it.layoutManager = LinearLayoutManager(this)
+ it.adapter = logAdapter
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/shuwei/intelligent/shelves/SettingActivity.kt b/app/src/main/java/com/shuwei/intelligent/shelves/activity/SettingActivity.kt
similarity index 87%
rename from app/src/main/java/com/shuwei/intelligent/shelves/SettingActivity.kt
rename to app/src/main/java/com/shuwei/intelligent/shelves/activity/SettingActivity.kt
index 2dc2e6a..4c96412 100644
--- a/app/src/main/java/com/shuwei/intelligent/shelves/SettingActivity.kt
+++ b/app/src/main/java/com/shuwei/intelligent/shelves/activity/SettingActivity.kt
@@ -1,14 +1,11 @@
-package com.shuwei.intelligent.shelves
+package com.shuwei.intelligent.shelves.activity
import android.os.Bundle
import android.os.Handler
import android.os.Looper
-import androidx.lifecycle.lifecycleScope
import com.shuwei.intelligent.shelves.base.BaseActivity
import com.shuwei.intelligent.shelves.databinding.ActivitySettingBinding
-import com.shuwei.intelligent.shelves.serial.SerialPortManager
import com.shuwei.intelligent.shelves.utils.KeyboardUtil
-import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
@@ -30,9 +27,7 @@ class SettingActivity: BaseActivity() {
record = cmd+"\n"+record
binding.tvCmdRecord.text = record
val realCmd = "${HomeActivity.HEADER}0F01${cmd}${HomeActivity.FOOTER}"
- lifecycleScope.launch {
- SerialPortManager.send(realCmd)
- }
+ sendCmd(realCmd)
}
binding.ivBack.setOnClickListener { finish() }
binding.root.setOnClickListener { v ->
diff --git a/app/src/main/java/com/shuwei/intelligent/shelves/ShelfActivity.kt b/app/src/main/java/com/shuwei/intelligent/shelves/activity/ShelfActivity.kt
similarity index 95%
rename from app/src/main/java/com/shuwei/intelligent/shelves/ShelfActivity.kt
rename to app/src/main/java/com/shuwei/intelligent/shelves/activity/ShelfActivity.kt
index 1cc0e4f..48c3b8e 100644
--- a/app/src/main/java/com/shuwei/intelligent/shelves/ShelfActivity.kt
+++ b/app/src/main/java/com/shuwei/intelligent/shelves/activity/ShelfActivity.kt
@@ -1,4 +1,4 @@
-package com.shuwei.intelligent.shelves
+package com.shuwei.intelligent.shelves.activity
import android.annotation.SuppressLint
import android.content.Intent
@@ -16,20 +16,20 @@ import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.GridLayoutManager
import com.chad.library.adapter4.util.setOnDebouncedItemClick
import com.scwang.smart.refresh.layout.constant.RefreshState
-import com.shuwei.intelligent.shelves.HomeActivity.Companion.DEVICE_INFO_CMD
+import com.shuwei.intelligent.shelves.App
+import com.shuwei.intelligent.shelves.R
+import com.shuwei.intelligent.shelves.activity.HomeActivity.Companion.DEVICE_INFO_CMD
import com.shuwei.intelligent.shelves.adapter.SearchAdapter
import com.shuwei.intelligent.shelves.base.BaseActivity
import com.shuwei.intelligent.shelves.databinding.ActivityShelfBinding
import com.shuwei.intelligent.shelves.model.ClearShelfEvent
import com.shuwei.intelligent.shelves.model.GoodsModel
-import com.shuwei.intelligent.shelves.model.GoodsRecord
import com.shuwei.intelligent.shelves.model.SendWeightEvent
import com.shuwei.intelligent.shelves.model.ShelfModel
import com.shuwei.intelligent.shelves.net.Loading
import com.shuwei.intelligent.shelves.net.NetViewModel
import com.shuwei.intelligent.shelves.net.RespData
import com.shuwei.intelligent.shelves.net.UiState
-import com.shuwei.intelligent.shelves.serial.SerialPortManager
import com.shuwei.intelligent.shelves.task.TaskManager
import com.shuwei.intelligent.shelves.utils.DateTimeUtil
import com.shuwei.intelligent.shelves.utils.KeyboardUtil
@@ -149,9 +149,8 @@ class ShelfActivity : BaseActivity() {
//binding.tvFoodWeight.text = "0克"
EventBus.getDefault().post(ClearShelfEvent(shelfModel!!.deviceNo, tempWeight))
}
+ sendCmd(DEVICE_INFO_CMD)
lifecycleScope.launch {
- SerialPortManager.send(DEVICE_INFO_CMD)
-
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.getGoodsListUiState.collect { state ->
when (state) {
@@ -360,8 +359,8 @@ class ShelfActivity : BaseActivity() {
public fun receiveWeightEvent(event: SendWeightEvent) {
if (event.shelfNo == (shelfModel?.deviceNo ?: 0)) {
val intervalTime = System.currentTimeMillis() - startTime
- Log.d(TAG, "receiveWeightEvent: ${event.shelfNo}号货架重量数据获取间隔时间为:$intervalTime")
val weight = event.weight
+ log("编号${event.shelfNo}货架获取重量成功:${weight}克,数据获取间隔时间为:${intervalTime}")
binding.tvFoodWeight.text = if(weight < 1000) "${weight}克" else "%.3f千克".format(weight/1000.0)
startTime = System.currentTimeMillis()
window.decorView.postDelayed({ Loading.dismiss() }, 2000)
@@ -374,13 +373,13 @@ class ShelfActivity : BaseActivity() {
val hex = shelfNo.toString(16).padStart(2, '0').uppercase()
Log.d(TAG, "onCreate: hex=$hex")
val zeroClearingCmd = "${HomeActivity.HEADER}0401${hex}${HomeActivity.FOOTER}"
- Log.d(TAG, "onCreate: zeroClearingCmd=$zeroClearingCmd")
- SerialPortManager.send(zeroClearingCmd)
+ log("编号${shelfNo}货架执行清零指令:${zeroClearingCmd}")
+ sendCmd(zeroClearingCmd)
//清零
realWeight = 0
// binding.tvFoodWeight.text = "${realWeight}克"
- SerialPortManager.send(DEVICE_INFO_CMD)
+ sendCmd(DEVICE_INFO_CMD)
startTime = System.currentTimeMillis()
Loading.show(this@ShelfActivity)
// window.decorView.postDelayed({ Loading.dismiss() }, 5000)
diff --git a/app/src/main/java/com/shuwei/intelligent/shelves/adapter/LogAdapter.kt b/app/src/main/java/com/shuwei/intelligent/shelves/adapter/LogAdapter.kt
new file mode 100644
index 0000000..7a61a62
--- /dev/null
+++ b/app/src/main/java/com/shuwei/intelligent/shelves/adapter/LogAdapter.kt
@@ -0,0 +1,25 @@
+package com.shuwei.intelligent.shelves.adapter
+
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import com.chad.library.adapter4.BaseQuickAdapter
+import com.chad.library.adapter4.viewholder.QuickViewHolder
+import com.shuwei.intelligent.shelves.databinding.ListItemLogBinding
+
+class LogAdapter(list: MutableList) :
+ BaseQuickAdapter(list) {
+
+ inner class VH(var binding: ListItemLogBinding) : QuickViewHolder(binding.root)
+
+ override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
+ val inflater = LayoutInflater.from(context)
+ val binding = ListItemLogBinding.inflate(inflater, parent, false)
+ return VH(binding)
+ }
+
+ override fun onBindViewHolder(holder: VH, position: Int, item: String?) {
+ holder.binding.tvLogName.text = item
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/shuwei/intelligent/shelves/base/BaseActivity.kt b/app/src/main/java/com/shuwei/intelligent/shelves/base/BaseActivity.kt
index 20e98f0..7a10c35 100644
--- a/app/src/main/java/com/shuwei/intelligent/shelves/base/BaseActivity.kt
+++ b/app/src/main/java/com/shuwei/intelligent/shelves/base/BaseActivity.kt
@@ -4,8 +4,8 @@ import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.os.Looper
+import android.util.Log
import android.view.View
-import android.widget.TextView
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
@@ -13,19 +13,22 @@ import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import com.gyf.immersionbar.BarHide
import com.gyf.immersionbar.ImmersionBar
-import com.shuwei.intelligent.shelves.HomeActivity
-import com.shuwei.intelligent.shelves.HomeActivity.Companion.LIGHT_CLOSE
-import com.shuwei.intelligent.shelves.HomeActivity.Companion.LIGHT_OPEN
+import com.shuwei.intelligent.shelves.activity.HomeActivity
+import com.shuwei.intelligent.shelves.activity.HomeActivity.Companion.LIGHT_CLOSE
+import com.shuwei.intelligent.shelves.activity.HomeActivity.Companion.LIGHT_OPEN
import com.shuwei.intelligent.shelves.R
-import com.shuwei.intelligent.shelves.SettingActivity
+import com.shuwei.intelligent.shelves.activity.LogActivity
+import com.shuwei.intelligent.shelves.activity.SettingActivity
import com.shuwei.intelligent.shelves.databinding.ActivityBaseBinding
import com.shuwei.intelligent.shelves.serial.SerialPortManager
+import com.shuwei.intelligent.shelves.utils.FileLogger
import com.shuwei.intelligent.shelves.utils.ext.clickWithDebounce
import com.shuwei.intelligent.shelves.utils.ext.startActivity
import kotlinx.coroutines.launch
@Suppress("DEPRECATION")
open class BaseActivity : AppCompatActivity() {
+ val TAG = this.javaClass.simpleName
private lateinit var binding: ActivityBaseBinding
private var launcher: ActivityResultLauncher? = null
@@ -143,7 +146,7 @@ open class BaseActivity : AppCompatActivity() {
if (tag == isOpen) {
return
}
- SerialPortManager.send(if (isOpen) LIGHT_OPEN else LIGHT_CLOSE)
+ sendCmd(if (isOpen) LIGHT_OPEN else LIGHT_CLOSE)
binding.tvLeftStatus.tag = isOpen
}
@@ -154,8 +157,24 @@ open class BaseActivity : AppCompatActivity() {
switchLight(tag.not())
}
binding.tvRightStatus.clickWithDebounce {
- startActivity { }
+ //startActivity { }
+ startActivity {
+ putExtra(LogActivity.IS_LOG_DIR, true)
+ }
}
}
+
+ fun sendCmd(cmd:String) {
+ lifecycleScope.launch {
+ SerialPortManager.send(cmd)
+ }
+ }
+
+ val fileLogger by lazy { FileLogger(this) }
+ fun log(message:String) {
+ Log.d(TAG, message)
+ fileLogger.log(message)
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/shuwei/intelligent/shelves/serial/SerialPortManager.kt b/app/src/main/java/com/shuwei/intelligent/shelves/serial/SerialPortManager.kt
index fca55e4..3727f44 100644
--- a/app/src/main/java/com/shuwei/intelligent/shelves/serial/SerialPortManager.kt
+++ b/app/src/main/java/com/shuwei/intelligent/shelves/serial/SerialPortManager.kt
@@ -21,36 +21,32 @@ object SerialPortManager {
private val scope = CoroutineScope(Dispatchers.IO)
// 打开串口
- fun open(): Boolean {
- lifecycleScope.launch {
- return try {
- serialPort = SerialPortFactory.create().apply {
- open(
- portName = portName,
- baudRate = baudRate,
- dataBits = 8,
- stopBits = 1,
- parity = SerialPort.PARITY_NONE
- )
- } as AndroidSerialPort?
- true
- } catch (e: Exception) {
- e.printStackTrace()
- false
- }
+ suspend fun open(): Boolean {
+ return try {
+ serialPort = SerialPortFactory.create().apply {
+ open(
+ portName = portName,
+ baudRate = baudRate,
+ dataBits = 8,
+ stopBits = 1,
+ parity = SerialPort.PARITY_NONE
+ )
+ } as AndroidSerialPort?
+ true
+ } catch (e: Exception) {
+ e.printStackTrace()
+ false
}
}
// 发送数据
- fun send(data: String): Boolean {
- lifecycleScope.launch {
- return try {
- serialPort?.write(data.hexToBytes())
- true
- } catch (e: Exception) {
- e.printStackTrace()
- false
- }
+ suspend fun send(data: String): Boolean {
+ return try {
+ serialPort?.write(data.hexToBytes())
+ true
+ } catch (e: Exception) {
+ e.printStackTrace()
+ false
}
}
diff --git a/app/src/main/java/com/shuwei/intelligent/shelves/task/SyncDeviceTask.kt b/app/src/main/java/com/shuwei/intelligent/shelves/task/SyncDeviceTask.kt
index 0989cde..6049f3e 100644
--- a/app/src/main/java/com/shuwei/intelligent/shelves/task/SyncDeviceTask.kt
+++ b/app/src/main/java/com/shuwei/intelligent/shelves/task/SyncDeviceTask.kt
@@ -4,7 +4,7 @@ import android.content.Context
import android.util.Log
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
-import com.shuwei.intelligent.shelves.HomeActivity
+import com.shuwei.intelligent.shelves.activity.HomeActivity
import com.shuwei.intelligent.shelves.serial.SerialPortManager
class SyncDeviceTask(appContext: Context, workerParams: WorkerParameters) :
@@ -14,7 +14,7 @@ class SyncDeviceTask(appContext: Context, workerParams: WorkerParameters) :
private const val TAG = "SyncDeviceTask"
}
- override fun doWork(): Result {
+ override suspend fun doWork(): Result {
return try {
// 执行后台任务逻辑
Log.d(TAG, "doWork: ----------SyncDeviceTask----------")
diff --git a/app/src/main/java/com/shuwei/intelligent/shelves/task/SyncTask.kt b/app/src/main/java/com/shuwei/intelligent/shelves/task/SyncTask.kt
index d633151..5fb8b52 100644
--- a/app/src/main/java/com/shuwei/intelligent/shelves/task/SyncTask.kt
+++ b/app/src/main/java/com/shuwei/intelligent/shelves/task/SyncTask.kt
@@ -5,7 +5,7 @@ import android.util.Log
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import com.shuwei.intelligent.shelves.App
-import com.shuwei.intelligent.shelves.HomeActivity
+import com.shuwei.intelligent.shelves.activity.HomeActivity
import com.shuwei.intelligent.shelves.model.ShelfBody
import com.shuwei.intelligent.shelves.net.apiService
import com.shuwei.intelligent.shelves.utils.ext.toJsonString
diff --git a/app/src/main/java/com/shuwei/intelligent/shelves/utils/BootReceiver.kt b/app/src/main/java/com/shuwei/intelligent/shelves/utils/BootReceiver.kt
index 8914d21..2b026e2 100644
--- a/app/src/main/java/com/shuwei/intelligent/shelves/utils/BootReceiver.kt
+++ b/app/src/main/java/com/shuwei/intelligent/shelves/utils/BootReceiver.kt
@@ -3,7 +3,7 @@ package com.shuwei.intelligent.shelves.utils
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
-import com.shuwei.intelligent.shelves.InitActivity
+import com.shuwei.intelligent.shelves.activity.InitActivity
import kotlin.jvm.java
class BootReceiver : BroadcastReceiver() {
diff --git a/app/src/main/java/com/shuwei/intelligent/shelves/utils/FileLogger.kt b/app/src/main/java/com/shuwei/intelligent/shelves/utils/FileLogger.kt
new file mode 100644
index 0000000..4a8d548
--- /dev/null
+++ b/app/src/main/java/com/shuwei/intelligent/shelves/utils/FileLogger.kt
@@ -0,0 +1,109 @@
+package com.shuwei.intelligent.shelves.utils
+
+import android.content.Context
+import java.io.*
+import java.text.SimpleDateFormat
+import java.util.*
+
+
+/**
+ * 文件日志记录器
+ * 功能:保存日志到本地文件,每条数据一行,每天生成新文件
+ */
+class FileLogger(private val context: Context) {
+
+ companion object {
+ private const val LOG_DIR = "logs"
+ private const val FILE_PREFIX = "log_"
+ private const val FILE_EXTENSION = ".txt"
+ private val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
+ private val timeFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
+ }
+
+ /**
+ * 记录日志
+ * @param message 日志消息
+ * @param level 日志级别
+ */
+ fun log(message: String, level: LogLevel = LogLevel.INFO) {
+ try {
+ val logEntry = formatLogEntry(message, level)
+ writeToFile(logEntry)
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }
+
+ /**
+ * 格式化日志条目
+ */
+ private fun formatLogEntry(message: String, level: LogLevel): String {
+ val timestamp = timeFormat.format(Date())
+ return "[$timestamp] [$level] $message\n"
+ }
+
+ /**
+ * 写入文件
+ */
+ private fun writeToFile(logEntry: String) {
+// val path = File(context.filesDir, LOG_DIR)
+// if (path.exists().not()) {
+// path.mkdirs()
+// }
+ val fileName = getCurrentDateFileName()
+// val file = File(path, fileName)
+// if (file.exists().not()) {
+// file.createNewFile()
+// }
+ val output = context.openFileOutput(fileName, Context.MODE_APPEND)
+
+ val writer = BufferedWriter(OutputStreamWriter(output))
+ writer.use {
+ it.write(logEntry)
+ }
+ }
+
+ /**
+ * 获取当前日期对应的文件名
+ */
+ private fun getCurrentDateFileName(): String {
+ val date = dateFormat.format(Date())
+ return "${FILE_PREFIX}${date}${FILE_EXTENSION}"
+ }
+
+ /**
+ * 读取指定日期的日志文件
+ * @param date 日期字符串,格式:yyyy-MM-dd
+ */
+ fun readLogsByDate(date: String): List {
+ val fileName = "${FILE_PREFIX}${date}${FILE_EXTENSION}"
+ return readLogsByName(fileName)
+ }
+ fun readLogsByName(fileName: String): List {
+ return try {
+ val input = context.openFileInput(fileName)
+ val reader = BufferedReader(InputStreamReader(input))
+ reader.useLines { lines ->
+ lines.toList()
+ }
+ } catch (e: FileNotFoundException) {
+ emptyList()
+ }
+ }
+
+ /**
+ * 获取所有日志文件列表
+ */
+ fun getLogFiles(): List {
+ return context.fileList()
+ .filter { it.startsWith(FILE_PREFIX) && it.endsWith(FILE_EXTENSION) }
+ //.map { it.replace(FILE_EXTENSION, "") }
+ }
+
+ /**
+ * 日志级别枚举
+ */
+ enum class LogLevel {
+ DEBUG, INFO, WARN, ERROR
+ }
+}
diff --git a/app/src/main/res/layout-sw600dp/activity_log_list.xml b/app/src/main/res/layout-sw600dp/activity_log_list.xml
new file mode 100644
index 0000000..df00a24
--- /dev/null
+++ b/app/src/main/res/layout-sw600dp/activity_log_list.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout-sw600dp/list_item_log.xml b/app/src/main/res/layout-sw600dp/list_item_log.xml
new file mode 100644
index 0000000..f9d0208
--- /dev/null
+++ b/app/src/main/res/layout-sw600dp/list_item_log.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_log_list.xml b/app/src/main/res/layout/activity_log_list.xml
new file mode 100644
index 0000000..df00a24
--- /dev/null
+++ b/app/src/main/res/layout/activity_log_list.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/list_item_log.xml b/app/src/main/res/layout/list_item_log.xml
new file mode 100644
index 0000000..f9d0208
--- /dev/null
+++ b/app/src/main/res/layout/list_item_log.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
\ No newline at end of file