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