Explorar el Código

调试页,报警屏蔽

ccc hace 5 meses
padre
commit
075adc4e9c
Se han modificado 25 ficheros con 875 adiciones y 96 borrados
  1. 15 0
      lib_base/src/main/java/com/quyunshuo/androidbaseframemvvm/base/addressenum/PlcAlarmAddressEnum.kt
  2. 10 0
      lib_base/src/main/res/values/strings.xml
  3. 1 1
      lib_common/src/main/res/layout/toast_error.xml
  4. 1 1
      lib_common/src/main/res/layout/toast_info.xml
  5. 1 1
      lib_common/src/main/res/layout/toast_success.xml
  6. 1 1
      lib_common/src/main/res/layout/toast_warn.xml
  7. 29 10
      module_backstage/src/main/java/com/module/backstage/activity/setting/SettingActivity.kt
  8. 47 18
      module_backstage/src/main/java/com/module/backstage/activity/setting/SettingViewModel.kt
  9. 65 0
      module_backstage/src/main/java/com/module/backstage/adapter/DebugAlarmAdapter.kt
  10. 1 0
      module_backstage/src/main/java/com/module/backstage/enums/SettingItemEnum.kt
  11. 146 0
      module_backstage/src/main/java/com/module/backstage/fragment/param/DebugAlarmFragment.kt
  12. 50 3
      module_backstage/src/main/java/com/module/backstage/fragment/param/DebugParamFragment.kt
  13. 4 3
      module_backstage/src/main/java/com/module/backstage/fragment/param/ParamSetFragment.kt
  14. 31 0
      module_backstage/src/main/java/com/module/backstage/repo/DebugAlarmFragmentRepo.kt
  15. 2 1
      module_backstage/src/main/java/com/module/backstage/repo/PermissionFragmentRepo.kt
  16. 98 0
      module_backstage/src/main/java/com/module/backstage/vm/DebugAlarmFragmentVM.kt
  17. 87 16
      module_backstage/src/main/java/com/module/backstage/vm/DebugParamFragmentVM.kt
  18. 18 0
      module_backstage/src/main/res/layout/backstage_fragment_debug_alarm.xml
  19. 26 0
      module_backstage/src/main/res/layout/backstage_item_debug_alarm.xml
  20. 4 0
      module_backstage/src/main/res/navigation/backstage_param_nav.xml
  21. 67 0
      serialport-api/src/main/java/com/hboxs/serialport/plc/thread/ThreadDebugAlarmParam.kt
  22. 113 3
      serialport-api/src/main/java/com/hboxs/serialport/plc/thread/ThreadDebugParamParam.kt
  23. 3 3
      serialport-api/src/main/java/com/hboxs/serialport/sbc/SBCHeartbeat.kt
  24. 51 35
      serialport-api/src/main/java/com/hboxs/serialport/sbc/VboxSerialPortReadThread.java
  25. 4 0
      serialport-api/src/main/java/com/hboxs/serialport/sbc/frame/VboxCommand.java

+ 15 - 0
lib_base/src/main/java/com/quyunshuo/androidbaseframemvvm/base/addressenum/PlcAlarmAddressEnum.kt

@@ -0,0 +1,15 @@
+package com.quyunshuo.androidbaseframemvvm.base.addressenum
+
+import com.quyunshuo.androidbaseframemvvm.base.R
+
+enum class PlcAlarmAddressEnum(val address: String, val aName: String, val aNameId:Int) {
+    Alarm01("0100", "玉米不爆开", R.string.base_plc_alarm_1),
+    Alarm02("0200", "缺杯",R.string.base_plc_alarm_2),
+    Alarm03("0300", "缺咸玉米",R.string.base_plc_alarm_3),
+    Alarm04("0400", "缺甜玉米",R.string.base_plc_alarm_4),
+    Alarm05("0500", "不升温",R.string.base_plc_alarm_5),
+    Alarm06("0600", "温度过高",R.string.base_plc_alarm_6),
+    Alarm07("0700", "挡片复位失败",R.string.base_plc_alarm_7),
+    Alarm08("0800", "玉米芯卡住",R.string.base_plc_alarm_8),
+
+}

+ 10 - 0
lib_base/src/main/res/values/strings.xml

@@ -36,6 +36,15 @@
     <string name="base_plc_param_7">加热时间</string>
     <string name="base_plc_param_8">制作时风速</string>
     <string name="base_plc_param_9">蒸发器保温上限</string>
+    <string name="base_plc_alarm_1">玉米不爆开</string>
+    <string name="base_plc_alarm_2">缺杯</string>
+    <string name="base_plc_alarm_3">缺咸玉米</string>
+    <string name="base_plc_alarm_4">缺甜玉米</string>
+    <string name="base_plc_alarm_5">不升温</string>
+    <string name="base_plc_alarm_6">温度过高</string>
+    <string name="base_plc_alarm_7">挡片复位失败</string>
+    <string name="base_plc_alarm_8">玉米芯卡住</string>
+
     <string name="base_pro_01">咸味爆米花</string>
     <string name="base_pro_02">甜味爆米花</string>
     <string name="base_two_code">微信支付宝</string>
@@ -85,6 +94,7 @@
     <string name="backstage_product_4">商品调试</string>
     <string name="backstage_param_set_1">调试页</string>
     <string name="backstage_param_set_2">通用参数</string>
+    <string name="backstage_param_set_3">报警屏蔽</string>
     <string name="backstage_back">返回</string>
     <string name="backstage_version">版本号:</string>
     <string name="backstage_connected">已连接:</string>

+ 1 - 1
lib_common/src/main/res/layout/toast_error.xml

@@ -26,7 +26,7 @@
         android:textColor="@android:color/white"
         android:layout_marginStart="20dp"
         android:layout_marginEnd="20dp"
-        android:textSize="75sp"
+        android:textSize="55sp"
         tools:text="我是 Toast 文本" />
 
 </LinearLayout>

+ 1 - 1
lib_common/src/main/res/layout/toast_info.xml

@@ -26,7 +26,7 @@
         android:layout_marginStart="20dp"
         android:layout_marginEnd="20dp"
         android:textColor="@android:color/white"
-        android:textSize="75sp"
+        android:textSize="55sp"
         tools:text="我是 Toast 文本" />
 
 </LinearLayout>

+ 1 - 1
lib_common/src/main/res/layout/toast_success.xml

@@ -26,7 +26,7 @@
         android:textColor="@android:color/white"
         android:layout_marginStart="20dp"
         android:layout_marginEnd="20dp"
-        android:textSize="75sp"
+        android:textSize="55sp"
         tools:text="我是 Toast 文本" />
 
 </LinearLayout>

+ 1 - 1
lib_common/src/main/res/layout/toast_warn.xml

@@ -26,7 +26,7 @@
         android:textColor="@android:color/white"
         android:layout_marginStart="20dp"
         android:layout_marginEnd="20dp"
-        android:textSize="75sp"
+        android:textSize="55sp"
         tools:text="我是 Toast 文本" />
 
 </LinearLayout>

+ 29 - 10
module_backstage/src/main/java/com/module/backstage/activity/setting/SettingActivity.kt

@@ -29,7 +29,9 @@ import com.hboxs.serialport.plc.DialogClickListener
 import com.hboxs.serialport.plc.message.Message
 import com.hboxs.serialport.sbc.SBCHeartbeat
 import com.hboxs.serialport.sbc.VBoxMessage
+import com.hboxs.serialport.sbc.VboxSerialPortSendQueue
 import com.hboxs.serialport.sbc.frame.VboxCommand
+import com.hboxs.serialport.sbc.frame.VboxWriteCommand
 import com.hjq.http.EasyHttp
 import com.hjq.http.listener.OnDownloadListener
 import com.hjq.http.model.HttpMethod
@@ -57,6 +59,10 @@ import com.quyunshuo.androidbaseframemvvm.common.util.ToastUtil
 import com.quyunshuo.androidbaseframemvvm.common.util.UiUtil
 import com.quyunshuo.androidbaseframemvvm.common.util.XLogUtil
 import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
 import org.greenrobot.eventbus.Subscribe
 import org.greenrobot.eventbus.ThreadMode
 import java.io.File
@@ -76,6 +82,7 @@ class SettingActivity : BaseActivity<BackstageActivitySettingBinding, SettingVie
     var connectionServerDialog: ConnectionServerDialog? = null
     var updateAppDialog: UpdateAppDialog? = null
     var apkInfoBean: ApkInfoBean? = null//更新信息
+    var windSpeed=0
 
     private var selectedMenuItemView: View?=null // 存储当前选中的MenuItem
     private var selectedMenuItemTextView: TextView?=null // 存储当前选中的MenuItem
@@ -143,7 +150,23 @@ class SettingActivity : BaseActivity<BackstageActivitySettingBinding, SettingVie
         mBinding.tvSoftwareVersion.text = "软件版本号:"+SBCHeartbeat.softwareVersion
         mBinding.tvCrateVersion.text = "机箱版本号:"+SBCHeartbeat.crateVersion
         mBinding.tvDevDogtag.text ="铭牌号:"+ SBCHeartbeat.devDogtag
+        mViewModel.getParamData();//读取参数
+    }
 
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun event(messageEvent: VBoxMessage) {
+        XLogUtil.d(messageEvent.cmd+":messageEvent.data:"+messageEvent.data)
+        Log.d(TAG, "settingdataevent0: "+messageEvent.data)
+        Log.d(TAG, "settingdataevent1: "+messageEvent.data.length)
+        when (messageEvent.cmd) {
+            VboxCommand.CMD_HEARTBEAT ->{
+                mViewModel.cmdHeartbeat(messageEvent)
+            }
+            VboxCommand.CMD_IO->{
+                mViewModel.cmdAllParam(messageEvent)
+            }
+            else -> {}
+        }
     }
 
     override fun initObserve() {
@@ -422,16 +445,6 @@ class SettingActivity : BaseActivity<BackstageActivitySettingBinding, SettingVie
         }
     }
 
-    @Subscribe(threadMode = ThreadMode.MAIN)
-    fun event(messageEvent: VBoxMessage) {
-        XLogUtil.d(messageEvent.cmd+":messageEvent.data:"+messageEvent.data)
-        when (messageEvent.cmd) {
-            VboxCommand.CMD_HEARTBEAT ->{
-                mViewModel.cmdHeartbeat(messageEvent)
-            }
-            else -> {}
-        }
-    }
 
     private fun setupCustomMenuItems() {
         // 清除默认菜单项
@@ -522,4 +535,10 @@ class SettingActivity : BaseActivity<BackstageActivitySettingBinding, SettingVie
             selectedMenuItemTextView = textView
         }
     }
+
+    override fun onDestroy() {
+        super.onDestroy()
+        Log.d(TAG, "onDestroy: ")
+        mViewModel.allParam=false
+    }
 }

+ 47 - 18
module_backstage/src/main/java/com/module/backstage/activity/setting/SettingViewModel.kt

@@ -9,8 +9,11 @@ import androidx.lifecycle.viewModelScope
 import com.google.gson.Gson
 import com.hboxs.serialport.plc.message.Message
 import com.hboxs.serialport.plc.thread.ThreadSettingParam
+import com.hboxs.serialport.sbc.SBCHeartbeat
 import com.hboxs.serialport.sbc.VBoxMessage
+import com.hboxs.serialport.sbc.VboxSerialPortSendQueue
 import com.hboxs.serialport.sbc.frame.VboxCommand
+import com.hboxs.serialport.sbc.frame.VboxWriteCommand
 import com.module.backstage.model.ApkInfoBean
 import com.quyunshuo.androidbaseframemvvm.base.BaseApplication
 import com.quyunshuo.androidbaseframemvvm.base.addressenum.PlcSettingAddressEnum
@@ -230,35 +233,61 @@ class SettingViewModel @Inject constructor(private val mRepo: SettingRepository)
 
     fun cmdHeartbeat(messageEvent: VBoxMessage) {
         val deviceState = messageEvent.data.substring(0, 2)//机器状态码
-        Log.d(TAG, "deviceState:1 "+messageEvent.data)
-        Log.d(TAG, "deviceState:2 "+deviceState)
-        when(deviceState){
-            "00"->{//刚上电
-
+        Log.d(TAG, "deviceState:1 " + messageEvent.data)
+        Log.d(TAG, "deviceState:2 " + deviceState)
+        when (deviceState) {
+            "00" -> {//刚上电
             }
-            "01"->{//开机中
+            "01" -> {//开机中
                 threadSettingParam.stopUp()
                 _isM3Success.value = true
             }
-            "02"->{//就绪待机,可以选购或制作下一杯
-
+            "02" -> {//就绪待机,可以选购或制作下一杯
             }
-            "03"->{//报警中
-
+            "03" -> {//报警中
             }
-            "04"->{//开始制作
-
+            "04" -> {//开始制作
             }
-            "05"->{//下玉米完毕
-
+            "05" -> {//下玉米完毕
             }
-            "07"->{//玉米爆开
-
+            "07" -> {//玉米爆开
             }
-            "10"->{//制作完成
+            "10" -> {//制作完成
+            }
+            else -> {}
+        }
+    }
+
+    fun cmdAllParam(messageEvent: VBoxMessage) {
+        Log.d(TAG, "getAllParam1: " + messageEvent.data.length)
+        Log.d(TAG, "getAllParam2: " + messageEvent.data.substring(0, 6))
+        val getAllParam = messageEvent.data.substring(0, 6)//查询参数指令标志
+        if (getAllParam == "00000A") {
+            SBCHeartbeat.windSpeedLow=messageEvent.data.substring(22, 24)
+            SBCHeartbeat.windSpeedMid=messageEvent.data.substring(24, 26)
+            SBCHeartbeat.windSpeedHei=messageEvent.data.substring(26, 28)
+            Log.d(TAG, "getWindSpeed:l "+SBCHeartbeat.windSpeedLow)
+            Log.d(TAG, "getWindSpeed:m "+SBCHeartbeat.windSpeedMid)
+            Log.d(TAG, "getWindSpeed:h "+SBCHeartbeat.windSpeedHei)
+        }
+    }
 
+    fun getParamData() {
+        CoroutineScope(Dispatchers.IO).launch {
+            launch {
+                while (allParam) {
+                    delay(1000)
+                    VboxSerialPortSendQueue.getInstance()
+                        .sendCommand(VboxWriteCommand(VboxCommand.CMD_IO, VboxCommand.GET_PARAM_ID))
+                    Log.d(TAG, "getAllParam0: ")
+                }
             }
-            else->{}
         }
     }
+
+    var allParam: Boolean = true
+        get() = field
+        set(value) {
+            field = value
+        }
 }

+ 65 - 0
module_backstage/src/main/java/com/module/backstage/adapter/DebugAlarmAdapter.kt

@@ -0,0 +1,65 @@
+package com.module.backstage.adapter
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import com.elvishew.xlog.XLog
+import com.module.backstage.databinding.BackstageItemDebugAlarmBinding
+import com.quyunshuo.androidbaseframemvvm.base.addressenum.PlcDebugAddressEnum
+import com.module.backstage.databinding.BackstageItemDebugParamBinding
+import com.quyunshuo.androidbaseframemvvm.base.addressenum.PlcAlarmAddressEnum
+import com.quyunshuo.androidbaseframemvvm.common.listener.AdapterClickListener
+import com.quyunshuo.androidbaseframemvvm.common.util.UiUtil
+import com.quyunshuo.androidbaseframemvvm.common.util.XLogUtil
+
+class DebugAlarmAdapter (var productList:MutableList<PlcAlarmAddressEnum>): RecyclerView.Adapter<DebugAlarmAdapter.MyViewHolder>() {
+
+    fun setItemListener(itemListener: AdapterClickListener?) {
+        this.itemListener = itemListener
+    }
+
+    private var itemListener: AdapterClickListener? = null
+    private var paraStateMap: MutableMap<String, String>? = null
+
+
+    inner class MyViewHolder(binding: BackstageItemDebugAlarmBinding): RecyclerView.ViewHolder(binding.root){
+        val mBinding = binding
+        fun bind(plcAlarmAddressEnum: PlcAlarmAddressEnum) {
+            mBinding.run {
+                cbManual.text = UiUtil.getStringRes(plcAlarmAddressEnum.aNameId)
+                cbManual.setOnClickListener { 
+                    itemListener?.onClickListener(it,layoutPosition,"")
+                }
+                if (paraStateMap != null) {
+                    XLogUtil.d(plcAlarmAddressEnum.address+":paraStateMap!![plcDebugAddressEnum.aName]:"+paraStateMap!![plcAlarmAddressEnum.address])
+                    if ("1" == (paraStateMap!![plcAlarmAddressEnum.address])) {
+                        cbManual.isChecked =true
+                    }else{
+                        cbManual.isChecked =false
+                    }
+                }
+            }
+        }
+
+    }
+
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
+        val projectVH = MyViewHolder(
+            BackstageItemDebugAlarmBinding.inflate(LayoutInflater.from(parent.context), parent, false)
+        )
+        return projectVH
+    }
+
+    override fun getItemCount(): Int {
+        return productList.size
+    }
+
+    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
+        holder.bind(productList.get(position))
+
+    }
+
+    fun setState(paraStateMap: MutableMap<String, String>) {
+        this.paraStateMap = paraStateMap
+    }
+}

+ 1 - 0
module_backstage/src/main/java/com/module/backstage/enums/SettingItemEnum.kt

@@ -24,5 +24,6 @@ enum class SettingItemEnum(val chName: String,val  nameId: Int,val iconId:Int,va
 
     PAR_1("调试页",R.string.backstage_param_set_1,R.drawable.icon_canshutiaozheng,14),
     PAR_2("通用参数",R.string.backstage_param_set_2,R.drawable.icon_zhifufangshi,15),
+    PAR_3("报警屏蔽",R.string.backstage_param_set_3,R.drawable.icon_zhifufangshi,16),
 }
 

+ 146 - 0
module_backstage/src/main/java/com/module/backstage/fragment/param/DebugAlarmFragment.kt

@@ -0,0 +1,146 @@
+package com.module.backstage.fragment.param
+
+import android.util.Log
+import android.view.View
+import android.widget.CheckBox
+import androidx.fragment.app.viewModels
+import androidx.recyclerview.widget.GridLayoutManager
+import com.hboxs.serialport.plc.DialogClickListener
+import com.hboxs.serialport.sbc.VBoxMessage
+import com.module.backstage.adapter.DebugAlarmAdapter
+import com.module.backstage.adapter.DebugParamAdapter
+import com.module.backstage.databinding.BackstageFragmentDebugAlarmBinding
+import com.module.backstage.dialog.OKCancelDialog
+import com.module.backstage.vm.DebugAlarmFragmentVM
+import com.quyunshuo.androidbaseframemvvm.common.listener.AdapterClickListener
+import com.quyunshuo.androidbaseframemvvm.base.ktx.observeLiveData
+import com.quyunshuo.androidbaseframemvvm.base.utils.RegisterEventBus
+import com.quyunshuo.androidbaseframemvvm.common.ui.BaseFragment
+import com.quyunshuo.androidbaseframemvvm.common.util.XLogUtil
+import dagger.hilt.android.AndroidEntryPoint
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+
+/**
+ * 调试页参数Fragment
+ *
+ * @author Qu Yunshuo
+ * @since 2021/8/1 11:46 下午
+ */
+@RegisterEventBus
+@AndroidEntryPoint
+class DebugAlarmFragment :
+    BaseFragment<BackstageFragmentDebugAlarmBinding, DebugAlarmFragmentVM>() {
+    private val TAG = "DebugParamFragment"
+    private var debugAlarmAdapter: DebugAlarmAdapter? = null
+    var okCancelDialog: OKCancelDialog? = null
+
+    override val mViewModel: DebugAlarmFragmentVM by viewModels()
+    override fun createVB() = BackstageFragmentDebugAlarmBinding.inflate(layoutInflater)
+
+    override fun onDestroyView() {
+        mBinding.debugRvAlarm.adapter = null
+        super.onDestroyView()
+    }
+    override fun BackstageFragmentDebugAlarmBinding.initView() {
+        with(debugRvAlarm){
+            //设置布局排列方式,默认垂直排列
+            val gridLayoutManager: GridLayoutManager =
+                GridLayoutManager(this@DebugAlarmFragment.context, 4, GridLayoutManager.VERTICAL, false)
+            layoutManager = gridLayoutManager
+            debugAlarmAdapter = DebugAlarmAdapter(mViewModel.getDebugAlarmData())
+            debugAlarmAdapter?.setItemListener(object: AdapterClickListener {
+                override fun onClickListener(view: View?, position: Int, data: String?) {
+                   var checkBox = view as CheckBox
+                    showOnOffDialog(checkBox.isChecked,position)
+
+                }
+            })
+            adapter = debugAlarmAdapter
+        }
+
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun event(messageEvent: VBoxMessage) {
+        XLogUtil.d("VBoxMessage:$messageEvent")
+        mViewModel.disposeData(messageEvent)
+    }
+
+    override fun initObserve() {
+        lifecycle.addObserver(mViewModel.getThreadDebugAlarmParam())
+        observeLiveData(mViewModel.paramDataList,::paramDataList)
+        observeLiveData(mViewModel.refreshPage,::refreshPage)
+    }
+
+    private fun refreshPage(b: Boolean?) {
+        debugAlarmAdapter?.setState(mViewModel._paramDataMap)
+        debugAlarmAdapter?.notifyDataSetChanged()
+    }
+
+    override fun initRequestData() {
+        mViewModel.getArticleData()
+    }
+
+    private fun paramDataList(string: String) {
+        var i = 0
+        val len = string.length
+        while (i < len) {
+            when (i) {
+                0->getValue(string,i,0)
+                2->getValue(string,i,1)
+                4->getValue(string,i,2)
+                6->getValue(string,i,3)
+                8->getValue(string,i,4)
+                10->getValue(string,i,5)
+                12->getValue(string,i,6)
+                14->getValue(string,i,7)
+            }
+            i++
+        }
+    }
+
+    /**
+     * 改变对应的状态
+     *
+     * @param lis      读取lpc返回值列表
+     * @param index    lis对应的值
+     * @param position 要改变的checkbox的位置
+     */
+    private fun getValue(string: String, index: Int, position: Int) {
+        val view: View = mBinding.debugRvAlarm.getChildAt(position)
+        if (null != mBinding.debugRvAlarm.getChildViewHolder(view)) {
+            val viewHolder: DebugAlarmAdapter.MyViewHolder =
+                mBinding.debugRvAlarm.getChildViewHolder(view) as DebugAlarmAdapter.MyViewHolder
+            Log.d(TAG, "位置: "+position+"当前按钮: "+viewHolder.mBinding.cbManual.isChecked+"  值:"+string[index])
+            if ('1' ==string[index]) {
+                //当它为选择状态时,无需设置,避免闪硕
+                if (!viewHolder.mBinding.cbManual.isChecked) { //如果已经选中了,那么我们这边就不会执行了。
+                    viewHolder.mBinding.cbManual.isChecked = true
+                }
+            } else {
+                if (viewHolder.mBinding.cbManual.isChecked) {
+                    viewHolder.mBinding.cbManual.isChecked = false
+                }
+            }
+        }
+    }
+
+    private fun showOnOffDialog(isChecked: Boolean, position: Int) {
+        if (okCancelDialog == null) {
+            okCancelDialog = this@DebugAlarmFragment.context?.let { OKCancelDialog(it) }
+        }
+        okCancelDialog?.setListener(object: DialogClickListener {
+            override fun onClickListener(type: Int, text: String?) {
+                when (type) {
+                    okCancelDialog?.type1-> {
+                        okCancelDialog?.dismiss()
+                        mViewModel.setBtnParam(isChecked,position)
+                    }
+                    else -> {}
+                }
+            }
+        })
+        okCancelDialog?.show()
+    }
+}

+ 50 - 3
module_backstage/src/main/java/com/module/backstage/fragment/param/DebugParamFragment.kt

@@ -6,6 +6,7 @@ import android.widget.CheckBox
 import androidx.fragment.app.viewModels
 import androidx.recyclerview.widget.GridLayoutManager
 import com.hboxs.serialport.plc.DialogClickListener
+import com.hboxs.serialport.sbc.SBCHeartbeat
 import com.hboxs.serialport.sbc.VBoxMessage
 import com.module.backstage.adapter.DebugParamAdapter
 import com.module.backstage.databinding.BackstageFragmentDebugParamBinding
@@ -76,6 +77,10 @@ class DebugParamFragment :
         observeLiveData(mViewModel.paramDataListM198,::setM198)
         observeLiveData(mViewModel.paramDataListM208,::setM208)
         observeLiveData(mViewModel.paramDataListM218,::setM218)
+        observeLiveData(mViewModel.lowSpeedChecked,::setWindLow)
+        observeLiveData(mViewModel.midSpeedChecked,::setWindMid)
+        observeLiveData(mViewModel.highSpeedChecked,::setWindHigh)
+        observeLiveData(mViewModel.paramDataList,::paramDataList)
         observeLiveData(mViewModel.refreshPage,::refreshPage)
     }
 
@@ -193,7 +198,20 @@ class DebugParamFragment :
             when (i) {
                 2-> getValue(lis, i, 22)
                 3 -> getValue(lis, i, 21)
+            }
+            i++
+        }
+    }
+
 
+    private fun paramDataList(lis: List<String>) {
+        var i = 0
+        val len = lis.size
+        Log.d(TAG, "paramDataList: "+lis)
+        while (i < len) {
+            when (i) {
+                0-> getValue(lis, i, 8)
+                1 -> getValue(lis, i, 10)
             }
             i++
         }
@@ -225,6 +243,38 @@ class DebugParamFragment :
         }
     }
 
+    private fun setWindLow(b: Boolean) {
+        getValue1(b,0)
+    }
+
+    private fun setWindMid(b: Boolean) {
+        getValue1(b,1)
+    }
+
+    private fun setWindHigh(b: Boolean) {
+        getValue1(b,2)
+    }
+
+
+    private fun getValue1(b: Boolean, position: Int) {
+        val view: View = mBinding.debugRvProduct.getChildAt(position)
+        if (null != mBinding.debugRvProduct.getChildViewHolder(view)) {
+            val viewHolder: DebugParamAdapter.MyViewHolder =
+                mBinding.debugRvProduct.getChildViewHolder(view) as DebugParamAdapter.MyViewHolder
+            Log.d(TAG, "position: "+position+"getValue isChecked: "+viewHolder.mBinding.cbManual.isChecked)
+            if (b) {
+                //当它为选择状态时,无需设置,避免闪硕
+                if (!viewHolder.mBinding.cbManual.isChecked) { //如果已经选中了,那么我们这边就不会执行了。
+                    viewHolder.mBinding.cbManual.isChecked = true
+                }
+            } else {
+                if (viewHolder.mBinding.cbManual.isChecked) {
+                    viewHolder.mBinding.cbManual.isChecked = false
+                }
+            }
+        }
+    }
+
 
     private fun showOnOffDialog(isChecked: Boolean, position: Int) {
         if (okCancelDialog == null) {
@@ -236,14 +286,11 @@ class DebugParamFragment :
                     okCancelDialog?.type1-> {
                         okCancelDialog?.dismiss()
                         mViewModel.setBtnParam(isChecked,position)
-
                     }
                     else -> {}
                 }
             }
-
         })
-
         okCancelDialog?.show()
     }
 

+ 4 - 3
module_backstage/src/main/java/com/module/backstage/fragment/param/ParamSetFragment.kt

@@ -29,12 +29,13 @@ import java.util.Arrays
 class ParamSetFragment : BaseFragment<BackstageFragmentParamSetBinding, ParamSetFragmentVM>() {
     private val CHANNELS = arrayOf(
         UiUtil.getStringRes(R.string.backstage_param_set_1),
-        UiUtil.getStringRes(R.string.backstage_param_set_2)
+        UiUtil.getStringRes(R.string.backstage_param_set_2),
+        UiUtil.getStringRes(R.string.backstage_param_set_3),
     )
     private val fragmentid = arrayOf(
         R.id.backstage_debugparamfragment,
-        R.id.backstage_generalparamfragment
-
+        R.id.backstage_generalparamfragment,
+        R.id.backstage_debugalarmfragment,
         )
     private val mDataList: List<String> = Arrays.asList(*CHANNELS)
 

+ 31 - 0
module_backstage/src/main/java/com/module/backstage/repo/DebugAlarmFragmentRepo.kt

@@ -0,0 +1,31 @@
+package com.module.backstage.repo
+
+import com.quyunshuo.androidbaseframemvvm.base.addressenum.PlcAlarmAddressEnum
+import com.quyunshuo.androidbaseframemvvm.base.mvvm.m.BaseRepository
+import java.util.Arrays
+import javax.inject.Inject
+
+/**
+ * HomeFragment的数据仓库层
+ *
+ * @author Qu Yunshuo
+ * @since 2021/8/5 10:59 下午
+ */
+class DebugAlarmFragmentRepo @Inject constructor() : BaseRepository() {
+
+    @Inject
+    lateinit var mApi: com.module.pay.service.HomeApiService
+
+    var arrayList: MutableList<PlcAlarmAddressEnum> = Arrays.asList(
+        PlcAlarmAddressEnum.Alarm01,
+        PlcAlarmAddressEnum.Alarm02,
+        PlcAlarmAddressEnum.Alarm03,
+        PlcAlarmAddressEnum.Alarm04,
+        PlcAlarmAddressEnum.Alarm05,
+        PlcAlarmAddressEnum.Alarm06,
+        PlcAlarmAddressEnum.Alarm07,
+        PlcAlarmAddressEnum.Alarm08,
+    )
+
+
+}

+ 2 - 1
module_backstage/src/main/java/com/module/backstage/repo/PermissionFragmentRepo.kt

@@ -33,7 +33,8 @@ class PermissionFragmentRepo @Inject constructor() : BaseRepository() {
         SettingItemEnum.PRO_3,
         SettingItemEnum.PRO_4,
         SettingItemEnum.PAR_1,
-        SettingItemEnum.PAR_2
+        SettingItemEnum.PAR_2,
+        SettingItemEnum.PAR_3
 
     )
 }

+ 98 - 0
module_backstage/src/main/java/com/module/backstage/vm/DebugAlarmFragmentVM.kt

@@ -0,0 +1,98 @@
+package com.module.backstage.vm
+
+import android.util.Log
+import androidx.lifecycle.LifecycleObserver
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import com.hboxs.serialport.plc.frame.ResponseFrame
+import com.hboxs.serialport.plc.message.Message
+import com.hboxs.serialport.plc.thread.ThreadDebugAlarmParam
+import com.hboxs.serialport.plc.thread.ThreadDebugParamParam
+import com.hboxs.serialport.plc.util.AsciiUtils
+import com.hboxs.serialport.plc.util.HexUtils
+import com.hboxs.serialport.plc.util.HexadecimalUtil
+import com.hboxs.serialport.sbc.SBCHeartbeat
+import com.hboxs.serialport.sbc.VBoxMessage
+import com.hboxs.serialport.sbc.frame.VboxCommand
+import com.module.backstage.R
+import com.module.backstage.repo.DebugAlarmFragmentRepo
+import com.quyunshuo.androidbaseframemvvm.base.addressenum.PlcAlarmAddressEnum
+import com.quyunshuo.androidbaseframemvvm.base.addressenum.PlcDebugAddressEnum
+import com.quyunshuo.androidbaseframemvvm.base.mvvm.vm.BaseViewModel
+import com.quyunshuo.androidbaseframemvvm.common.util.ToastUtil
+import com.quyunshuo.androidbaseframemvvm.common.util.UiUtil
+import dagger.hilt.android.lifecycle.HiltViewModel
+import java.util.Arrays
+import javax.inject.Inject
+
+/**
+ * HomeFragment 的 VM 层
+ *
+ * @author Qu Yunshuo
+ * @since 2021/8/5 11:11 下午
+ */
+@HiltViewModel//@HiltViewModel 注解的作用是将 ViewModel 标记为可以由 Hilt 管理的依赖项。当你将 @HiltViewModel 注解添加到 ViewModel 类上时,Hilt 会自动处理 ViewModel 的创建和注入过程。这样,你就不需要手动调用 ViewModelProvider 来获取 ViewModel 实例了。
+class DebugAlarmFragmentVM @Inject constructor(private val mRepo: DebugAlarmFragmentRepo) :
+    BaseViewModel() {
+    private val TAG = "DebugParamFragmentVM"
+    private var threadDebugAlarmParam = ThreadDebugAlarmParam()
+
+
+    private var _paramDataList = MutableLiveData<String>()
+    val paramDataList: MutableLiveData<String> get() = _paramDataList
+    /**
+     * 获取文章数据
+     */
+    fun getArticleData() {
+
+    }
+    fun getDebugAlarmData(): MutableList<PlcAlarmAddressEnum> {
+        return mRepo.arrayList
+    }
+
+    fun getThreadDebugAlarmParam(): LifecycleObserver {
+        return threadDebugAlarmParam
+    }
+
+
+    var _paramDataMap = mutableMapOf<String, String>()
+        get() = field
+
+    private val _refreshPage = MutableLiveData<Boolean>();
+    val refreshPage: MutableLiveData<Boolean> get() = _refreshPage
+
+    //按鈕置位复位
+    fun setBtnParam(checked: Boolean, position: Int) {
+        val plcAlarmAddressEnum: PlcAlarmAddressEnum = mRepo.arrayList.get(position)
+        Log.d(TAG, "setBtnParam: "+plcAlarmAddressEnum.aName+":"+plcAlarmAddressEnum.address+":"+checked)
+        if (checked) {
+            threadDebugAlarmParam.setBtn(plcAlarmAddressEnum.address)
+        } else {
+            threadDebugAlarmParam.rstBtn(plcAlarmAddressEnum.address)
+        }
+    }
+
+    fun disposeData(messageEvent: VBoxMessage) {
+        Log.d(TAG, messageEvent.cmd+"messageEvent event: "+messageEvent.data)
+        val getAllParam = messageEvent.data.substring(0, 6)//查询参数指令标志
+        if (getAllParam != "00000A") {
+            return
+        }
+        when (messageEvent.cmd) {
+            VboxCommand.CMD_HEARTBEAT -> {
+                cmdHeartbeat(messageEvent)
+            }
+        }
+    }
+
+    private fun cmdHeartbeat(messageEvent: VBoxMessage) {
+        //调试页的内容
+        val data = messageEvent.data.substring(7,22)
+        updateOtherState(data)
+    }
+
+    fun updateOtherState(string: String) {
+        Log.d(TAG, "updateOtherStateAlarm:1 "+string)
+        paramDataList.value = string
+    }
+}

+ 87 - 16
module_backstage/src/main/java/com/module/backstage/vm/DebugParamFragmentVM.kt

@@ -2,6 +2,7 @@ package com.module.backstage.vm
 
 import android.util.Log
 import androidx.lifecycle.LifecycleObserver
+import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import com.hboxs.serialport.plc.frame.ResponseFrame
 import com.hboxs.serialport.plc.message.Message
@@ -9,6 +10,7 @@ import com.hboxs.serialport.plc.thread.ThreadDebugParamParam
 import com.hboxs.serialport.plc.util.AsciiUtils
 import com.hboxs.serialport.plc.util.HexUtils
 import com.hboxs.serialport.plc.util.HexadecimalUtil
+import com.hboxs.serialport.sbc.SBCHeartbeat
 import com.hboxs.serialport.sbc.VBoxMessage
 import com.hboxs.serialport.sbc.frame.VboxCommand
 import com.module.backstage.R
@@ -63,8 +65,21 @@ class DebugParamFragmentVM @Inject constructor(private val mRepo: DebugParamFrag
     var _paramDataMap = mutableMapOf<String, String>()
         get() = field
 
+    private val _lowSpeedChecked = MutableLiveData<Boolean>()
+    val lowSpeedChecked: LiveData<Boolean> get() = _lowSpeedChecked
+
+    private val _midSpeedChecked = MutableLiveData<Boolean>()
+    val midSpeedChecked: LiveData<Boolean> get() = _midSpeedChecked
+
+    private val _highSpeedChecked = MutableLiveData<Boolean>()
+    val highSpeedChecked: LiveData<Boolean> get() = _highSpeedChecked
+
+    private var _paramDataList = MutableLiveData<List<String>>()
+    val paramDataList: MutableLiveData<List<String>> get() = _paramDataList
+
     private val _refreshPage = MutableLiveData<Boolean>();
     val refreshPage: MutableLiveData<Boolean> get() = _refreshPage
+
     /**
      * 获取文章数据
      */
@@ -137,8 +152,9 @@ class DebugParamFragmentVM @Inject constructor(private val mRepo: DebugParamFrag
         //翻转后的数据
         val s1 = HexadecimalUtil.flipString(s, 8)
         val stringBuilder = StringBuilder(s1)
-        val lis = Arrays.asList(*stringBuilder.reverse().toString().split("".toRegex()).dropLastWhile { it.isEmpty() }
-            .toTypedArray())
+        val lis = Arrays.asList(
+            *stringBuilder.reverse().toString().split("".toRegex()).dropLastWhile { it.isEmpty() }
+                .toTypedArray())
         val list: ArrayList<String> = ArrayList(lis)
         list.removeAt(0)
         Log.d(TAG, "M228: " + list)
@@ -151,8 +167,9 @@ class DebugParamFragmentVM @Inject constructor(private val mRepo: DebugParamFrag
         //翻转后的数据
 //        val s1 = HexadecimalUtil.flipString(s, 8)
         val stringBuilder = StringBuilder(s)
-        val lis = Arrays.asList(*stringBuilder.reverse().toString().split("".toRegex()).dropLastWhile { it.isEmpty() }
-            .toTypedArray())
+        val lis = Arrays.asList(
+            *stringBuilder.reverse().toString().split("".toRegex()).dropLastWhile { it.isEmpty() }
+                .toTypedArray())
         val list: ArrayList<String> = ArrayList(lis)
         list.removeAt(0)
         Log.d(TAG, "M218: " + list)
@@ -165,8 +182,9 @@ class DebugParamFragmentVM @Inject constructor(private val mRepo: DebugParamFrag
         //翻转后的数据
 //        val s1 = HexadecimalUtil.flipString(s, 8)
         val stringBuilder = StringBuilder(s)
-        val lis = Arrays.asList(*stringBuilder.reverse().toString().split("".toRegex()).dropLastWhile { it.isEmpty() }
-            .toTypedArray())
+        val lis = Arrays.asList(
+            *stringBuilder.reverse().toString().split("".toRegex()).dropLastWhile { it.isEmpty() }
+                .toTypedArray())
         val list: ArrayList<String> = ArrayList(lis)
         list.removeAt(0)
         Log.d(TAG, "M208: " + list)
@@ -179,8 +197,9 @@ class DebugParamFragmentVM @Inject constructor(private val mRepo: DebugParamFrag
         //翻转后的数据
         val s1 = HexadecimalUtil.flipString(s, 8)
         val stringBuilder = StringBuilder(s1)
-        val lis = Arrays.asList(*stringBuilder.reverse().toString().split("".toRegex()).dropLastWhile { it.isEmpty() }
-            .toTypedArray())
+        val lis = Arrays.asList(
+            *stringBuilder.reverse().toString().split("".toRegex()).dropLastWhile { it.isEmpty() }
+                .toTypedArray())
         val list: ArrayList<String> = ArrayList(lis)
         list.removeAt(0)
         Log.d(TAG, "M198: " + list)
@@ -219,8 +238,9 @@ class DebugParamFragmentVM @Inject constructor(private val mRepo: DebugParamFrag
         //翻转后的数据
         val s1 = HexadecimalUtil.flipString(s, 8)
         val stringBuilder = StringBuilder(s1)
-        val lis = Arrays.asList(*stringBuilder.reverse().toString().split("".toRegex()).dropLastWhile { it.isEmpty() }
-            .toTypedArray())
+        val lis = Arrays.asList(
+            *stringBuilder.reverse().toString().split("".toRegex()).dropLastWhile { it.isEmpty() }
+                .toTypedArray())
         val list: ArrayList<String> = ArrayList(lis)
         list.removeAt(0)
         Log.d(TAG, "M166: " + list)
@@ -244,7 +264,10 @@ class DebugParamFragmentVM @Inject constructor(private val mRepo: DebugParamFrag
     //按鈕置位复位
     fun setBtnParam(checked: Boolean, position: Int) {
         val plcDebugAddressEnum: PlcDebugAddressEnum = mRepo.arrayList.get(position)
-        Log.d(TAG, "setBtnParam: "+plcDebugAddressEnum.aName+":"+plcDebugAddressEnum.address+":"+checked)
+        Log.d(
+            TAG,
+            "setBtnParam: " + plcDebugAddressEnum.aName + ":" + plcDebugAddressEnum.address + ":" + checked
+        )
         if (checked) {
             threadDebugParamParam.setBtn(plcDebugAddressEnum.address)
         } else {
@@ -253,6 +276,11 @@ class DebugParamFragmentVM @Inject constructor(private val mRepo: DebugParamFrag
     }
 
     fun disposeData(messageEvent: VBoxMessage) {
+        Log.d(TAG, messageEvent.cmd + "messageEvent event: " + messageEvent.data)
+        val getAllParam = messageEvent.data.substring(0, 6)//查询参数指令标志
+        if (getAllParam != "000060") {
+            return
+        }
         when (messageEvent.cmd) {
             VboxCommand.CMD_HEARTBEAT -> {
                 cmdHeartbeat(messageEvent)
@@ -262,13 +290,56 @@ class DebugParamFragmentVM @Inject constructor(private val mRepo: DebugParamFrag
 
     private fun cmdHeartbeat(messageEvent: VBoxMessage) {
         //调试页的内容
-        val data = messageEvent.data.substring(26,32)
+        val getWindSpeed = messageEvent.data.substring(38, 40)//气泵风速
+        updatePumpState(getWindSpeed)
+        val data = messageEvent.data.substring(26, 32)
         val hexStr2BinStr = HexUtils.hexStr2BinStr(data)
         val split = hexStr2BinStr.split("")
-        _paramDataMap.clear()
-        for ((index, plcDebugAddressEnum) in mRepo.arrayList.withIndex()) {
-            _paramDataMap[plcDebugAddressEnum.address] = split[index+1]
+        updateOtherState(split)
+//        _paramDataMap.clear()
+//        for ((index, plcDebugAddressEnum) in mRepo.arrayList.withIndex()) {
+//            _paramDataMap[plcDebugAddressEnum.address] = split[index+1]
+//        }
+//        _refreshPage.value = true
+    }
+
+
+    // 更新气泵状态
+    fun updatePumpState(getWindSpeed: String) {
+        when (getWindSpeed) {
+            SBCHeartbeat.windSpeedLow -> {
+                Log.d(TAG, "updatePumpState: windSpeedLow" + getWindSpeed)
+                _lowSpeedChecked.value = true
+                _midSpeedChecked.value = false
+                _highSpeedChecked.value = false
+            }
+
+            SBCHeartbeat.windSpeedMid -> {
+                Log.d(TAG, "updatePumpState: windSpeedMid" + getWindSpeed)
+                _lowSpeedChecked.value = false
+                _midSpeedChecked.value = true
+                _highSpeedChecked.value = false
+            }
+
+            SBCHeartbeat.windSpeedHei -> {
+                Log.d(TAG, "updatePumpState: windSpeedHei" + getWindSpeed)
+                _lowSpeedChecked.value = false
+                _midSpeedChecked.value = false
+                _highSpeedChecked.value = true
+            }
+
+            else -> {
+                Log.d(TAG, "updatePumpState: " + getWindSpeed)
+                _lowSpeedChecked.value = false
+                _midSpeedChecked.value = false
+                _highSpeedChecked.value = false
+            }
         }
-        _refreshPage.value = true
+    }
+
+    // 更新其他状态
+    fun updateOtherState(lis: List<String>) {
+        val cleanedList = lis.filter { it.isNotEmpty() }
+        paramDataList.value = cleanedList
     }
 }

+ 18 - 0
module_backstage/src/main/res/layout/backstage_fragment_debug_alarm.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/debug_rv_alarm"
+        android:layout_width="match_parent"
+        android:maxHeight="2080dp"
+        android:layout_height="match_parent"
+        android:layout_marginVertical="40dp"
+        android:layout_marginLeft="10dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 26 - 0
module_backstage/src/main/res/layout/backstage_item_debug_alarm.xml

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_marginEnd="20dp"
+    android:layout_marginBottom="20dp"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+
+    <CheckBox
+        android:id="@+id/cb_manual"
+        android:layout_width="340dp"
+        android:maxHeight="180dp"
+        android:layout_height="180dp"
+        android:minHeight="78dp"
+        android:background="@drawable/backstage_selector_debug_param_cb_bg"
+        android:button="@null"
+        android:checked="false"
+        android:padding="10dp"
+        android:text="报警屏蔽按钮"
+        android:gravity="center"
+        android:textColor="@drawable/backstage_selector_debug_param_cb_color"
+        android:textSize="46sp"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 4 - 0
module_backstage/src/main/res/navigation/backstage_param_nav.xml

@@ -28,4 +28,8 @@
         android:id="@+id/backstage_debugparamfragment"
         android:name="com.module.backstage.fragment.param.DebugParamFragment"
         android:label="DebugParamFragment" />
+    <fragment
+        android:id="@+id/backstage_debugalarmfragment"
+        android:name="com.module.backstage.fragment.param.DebugAlarmFragment"
+        android:label="DebugAlarmFragment" />
 </navigation>

+ 67 - 0
serialport-api/src/main/java/com/hboxs/serialport/plc/thread/ThreadDebugAlarmParam.kt

@@ -0,0 +1,67 @@
+package com.hboxs.serialport.plc.thread
+
+import android.util.Log
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleObserver
+import androidx.lifecycle.OnLifecycleEvent
+import com.hboxs.serialport.plc.SerialPortSendQueue
+import com.hboxs.serialport.plc.frame.ReadCommandFrame
+import com.hboxs.serialport.plc.frame.RstCommandFrame
+import com.hboxs.serialport.plc.frame.SetCommandFrame
+import com.hboxs.serialport.sbc.VboxSerialPortSendQueue
+import com.hboxs.serialport.sbc.frame.VboxCommand
+import com.hboxs.serialport.sbc.frame.VboxWriteCommand
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+class ThreadDebugAlarmParam : LifecycleObserver {
+
+    private val TAG = "ThreadGeneralParam"
+
+    var jobSetBtn: Job? = null
+        get() = field
+    var jobRstBtn: Job? = null
+        get() = field
+
+    @OnLifecycleEvent(Lifecycle.Event.ON_START)
+    fun startRead() {
+        // 启动协程
+    }
+
+    fun setBtn(address: String) {
+        VboxSerialPortSendQueue.getInstance()
+            .sendCommand(
+                VboxWriteCommand(
+                    VboxCommand.CMD_IO,
+                    VboxCommand.EARLY_WARN_ID + address + "01"
+                )
+            )
+        Log.d(TAG, "setBtn: 预警开启")
+    }
+
+    fun rstBtn(address: String) {
+        VboxSerialPortSendQueue.getInstance()
+            .sendCommand(
+                VboxWriteCommand(
+                    VboxCommand.CMD_IO,
+                    VboxCommand.EARLY_WARN_ID + address + "00"
+                )
+            )
+        Log.d(TAG, "setBtn: 预警关闭")
+    }
+
+
+    /**
+     * 关掉线程池
+     */
+    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
+    fun destroy() {
+        //避免线程池关不掉
+        jobSetBtn?.cancel()
+        jobRstBtn?.cancel()
+    }
+
+}

+ 113 - 3
serialport-api/src/main/java/com/hboxs/serialport/plc/thread/ThreadDebugParamParam.kt

@@ -39,6 +39,95 @@ class ThreadDebugParamParam : LifecycleObserver {
     var jobM228: Job? = null
         get() = field
 
+    var jobR02: Job? = null
+        get() = field
+    var jobR03: Job? = null
+        get() = field
+    var jobR04: Job? = null
+        get() = field
+    var jobR05: Job? = null
+        get() = field
+    var jobR06: Job? = null
+        get() = field
+    var jobR07: Job? = null
+        get() = field
+    var jobR08: Job? = null
+        get() = field
+    var jobR09: Job? = null
+        get() = field
+    var jobR10: Job? = null
+        get() = field
+    var jobR11: Job? = null
+        get() = field
+    var jobR12: Job? = null
+        get() = field
+
+    var isActiveR02: Boolean = true
+        get() = field
+        set(value) {
+            field = value
+        }
+
+    var isActiveR03: Boolean = true
+        get() = field
+        set(value) {
+            field = value
+        }
+
+    var isActiveR04: Boolean = true
+        get() = field
+        set(value) {
+            field = value
+        }
+
+    var isActiveR05: Boolean = true
+        get() = field
+        set(value) {
+            field = value
+        }
+
+    var isActiveR06: Boolean = true
+        get() = field
+        set(value) {
+            field = value
+        }
+
+    var isActiveR07: Boolean = true
+        get() = field
+        set(value) {
+            field = value
+        }
+
+    var isActiveR08: Boolean = true
+        get() = field
+        set(value) {
+            field = value
+        }
+
+    var isActiveR09: Boolean = true
+        get() = field
+        set(value) {
+            field = value
+        }
+
+    var isActiveR10: Boolean = true
+        get() = field
+        set(value) {
+            field = value
+        }
+
+    var isActiveR11: Boolean = true
+        get() = field
+        set(value) {
+            field = value
+        }
+    var isActiveR12: Boolean = true
+        get() = field
+        set(value) {
+            field = value
+        }
+
+
     var jobSetBtn: Job? = null
         get() = field
     var jobRstBtn: Job? = null
@@ -214,12 +303,22 @@ class ThreadDebugParamParam : LifecycleObserver {
 
     fun setBtn(address: String) {
         VboxSerialPortSendQueue.getInstance()
-            .sendCommand(VboxWriteCommand(VboxCommand.CMD_IO, VboxCommand.DEBUG_ID+address+"01"))
+            .sendCommand(
+                VboxWriteCommand(
+                    VboxCommand.CMD_IO,
+                    VboxCommand.DEBUG_ID + address + "01"
+                )
+            )
     }
 
     fun rstBtn(address: String) {
         VboxSerialPortSendQueue.getInstance()
-            .sendCommand(VboxWriteCommand(VboxCommand.CMD_IO, VboxCommand.DEBUG_ID+address+"00"))
+            .sendCommand(
+                VboxWriteCommand(
+                    VboxCommand.CMD_IO,
+                    VboxCommand.DEBUG_ID + address + "00"
+                )
+            )
     }
 
 
@@ -237,10 +336,21 @@ class ThreadDebugParamParam : LifecycleObserver {
         jobM208?.cancel()
         jobM218?.cancel()
         jobM228?.cancel()
-
         jobSetBtn?.cancel()
         jobRstBtn?.cancel()
 
+        jobR02?.cancel()
+        jobR03?.cancel()
+        jobR04?.cancel()
+        jobR05?.cancel()
+        jobR06?.cancel()
+        jobR07?.cancel()
+        jobR08?.cancel()
+        jobR09?.cancel()
+        jobR10?.cancel()
+        jobR11?.cancel()
+        jobR12?.cancel()
+
     }
 
 

+ 3 - 3
serialport-api/src/main/java/com/hboxs/serialport/sbc/SBCHeartbeat.kt

@@ -1,7 +1,5 @@
 package com.hboxs.serialport.sbc
 
-import java.math.BigDecimal
-
 /**
  * 后台参数数据
  */
@@ -23,5 +21,7 @@ object SBCHeartbeat {
     var outsideTemp:String = "40"//柜外温度
     var outsideHumidity:String = "40"//柜外湿度
 
-
+    var windSpeedLow:String =""//气泵低速
+    var windSpeedMid:String =""//气泵低速
+    var windSpeedHei:String =""//气泵低速
 }

+ 51 - 35
serialport-api/src/main/java/com/hboxs/serialport/sbc/VboxSerialPortReadThread.java

@@ -18,7 +18,6 @@ import java.io.IOException;
 import java.io.InputStream;
 
 
-
 /**
  * 串口读取线程
  */
@@ -28,10 +27,11 @@ public class VboxSerialPortReadThread extends Thread {
     private BufferedInputStream mInputStream;
     private boolean running;
     private VboxCommandFrame commandFrame;
-    private VboxSerialPortSendQueue vboxSerialPortSendQueue ;
+    private VboxSerialPortSendQueue vboxSerialPortSendQueue;
+
     public VboxSerialPortReadThread(InputStream inputStream) {
         mInputStream = new BufferedInputStream(inputStream);
-        vboxSerialPortSendQueue =  VboxSerialPortSendQueue.getInstance();
+        vboxSerialPortSendQueue = VboxSerialPortSendQueue.getInstance();
     }
 
 
@@ -69,46 +69,62 @@ public class VboxSerialPortReadThread extends Thread {
         if (size >= 1) {
             //现在来增加,这个数据究竟是谁。
             commandFrame = vboxSerialPortSendQueue.getCurrentFrame();
-            if (commandFrame ==null) {
+            if (commandFrame == null) {
                 return;
             }
             vboxSerialPortSendQueue.setReceived();//收到数据了,要停止了。
 
             // 处理接收到的数据
-            String s1 = ByteUtil.ByteArrToHex(received,0,size);
-            XLogUtil.INSTANCE.d("readData s1:"+s1);
-            // 1. 找帧数据,stx开始,etx结束
-            int start = -1, end = -1;
-            for (int i = 0; i < size; i+=2) {
-                ByteUtil.ByteArrToHex(received,i,4);
-                if (VboxCommand.STX.equals(ByteUtil.Byte2Hex(received[i])+ByteUtil.Byte2Hex(received[i+1]))) {
-                    start = i;
-                } else if (VboxCommand.ETX.equals(ByteUtil.Byte2Hex(received[i])+ByteUtil.Byte2Hex(received[i+1]))) {
-                    end = i;
-                    break;
-                }
+            String s1 = ByteUtil.ByteArrToHex(received, 0, size);
+            XLogUtil.INSTANCE.d("readData s1:" + s1);
+
+// 1. 如果字节数组长度是单数,补全为双数
+            if (size % 2 != 0) {
+                byte[] paddedReceived = new byte[size + 1];
+                System.arraycopy(received, 0, paddedReceived, 0, size);
+                paddedReceived[size] = 0x00; // 补全一个字节
+                received = paddedReceived;
+                size = received.length; // 更新 size
             }
-            XLogUtil.INSTANCE.d("readData:"+s1+":"+start+":"+end);
-            //2. start 和 end 整数表示收到的数据包包含帧数据
-            if (start >= 0 && end >= 0) {
-                start += 2;//去除字节长度、CMD指令
-                byte[] data = new byte[]{};
-                if (start < end) {
-                    int len = end - start;
-                    data = new byte[len];
-                    System.arraycopy(received, start, data, 0, len);
+
+            // 2. 将字节数组转换为十六进制字符串
+            String hexData = ByteUtil.ByteArrToHex(received, 0, size);
+            // 3. 使用循环逐个查找帧
+            int startIndex = 0;
+            while (startIndex < hexData.length()) {
+                // 查找 STX 的位置
+                int stxIndex = hexData.indexOf(VboxCommand.STX, startIndex);
+                if (stxIndex == -1) {
+                    break; // 没有找到 STX,退出循环
                 }
-                VboxResponseFrame frame = new VboxResponseFrame();
-                frame.setData(data);
-                //3. 得到最终的数据,要进行推送。
-                String finallyData = ByteUtil.ByteArrToHex(data);
-                Log.d(TAG,  "finallyData onDataReceive11: " + finallyData);
-                Log.d(TAG,  "finallyData onDataReceive12: " + commandFrame);//为null,为什么呢?
-                Log.d(TAG,  "finallyData onDataReceive13: " + commandFrame.getCmd());//为null,为什么呢?
-
-                EventBus.getDefault().post(new VBoxMessage(commandFrame.getCmd(), finallyData));
-            }
 
+                // 查找 ETX 的位置
+                int etxIndex = hexData.indexOf(VboxCommand.ETX, stxIndex + VboxCommand.STX.length());
+                if (etxIndex == -1) {
+                    break; // 没有找到 ETX,退出循环
+                }
+                // 4. 提取一个完整的帧
+                String frame = hexData.substring(stxIndex, etxIndex + VboxCommand.ETX.length());
+                // 5. 检查头和尾是否匹配
+                if (frame.startsWith(VboxCommand.STX) && frame.endsWith(VboxCommand.ETX)) {
+                    // 去掉头和尾的 4 个字符(STX 和 ETX)
+                    String finallyData = frame.substring(VboxCommand.STX.length(), frame.length() - VboxCommand.ETX.length());
+
+                    // 6. 创建 VboxResponseFrame 对象并设置数据
+                    VboxResponseFrame responseFrame = new VboxResponseFrame();
+                    responseFrame.setData(ByteUtil.HexToByteArr(finallyData));
+                    // 7. 打印最终数据
+                    Log.d(TAG, "finallyData onDataReceive11: " + finallyData);
+                    Log.d(TAG, "finallyData onDataReceive12: " + commandFrame);
+                    Log.d(TAG, "finallyData onDataReceive13: " + commandFrame.getCmd());
+
+                    // 8. 通过 EventBus 推送数据
+                    EventBus.getDefault().post(new VBoxMessage(commandFrame.getCmd(), finallyData));
+                }
+
+                // 9. 更新 startIndex,继续查找下一个帧
+                startIndex = etxIndex + VboxCommand.ETX.length();
+            }
         }
     }
 

+ 4 - 0
serialport-api/src/main/java/com/hboxs/serialport/sbc/frame/VboxCommand.java

@@ -18,6 +18,10 @@ public class VboxCommand {
      */
     public final static String DEBUG_ID = "00FB";
     /**
+     * 查询后台所有参数指令
+     */
+    public final static String GET_PARAM_ID = "00FF00";
+    /**
      * 制作指令
      */
     public final static String MAKE_ID = "00FC";