bjb 3 долоо хоног өмнө
parent
commit
f02d72b6d8

+ 5 - 2
app/src/main/AndroidManifest.xml

@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools">
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
 
     <application
         android:allowBackup="true"
@@ -22,6 +21,10 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+        <activity
+            android:name=".CtrlActivity"
+            android:exported="true"
+            android:theme="@style/Theme.CommunicationDemo" />
     </application>
 
 </manifest>

+ 106 - 0
app/src/main/java/com/iscs/comm/CtrlActivity.kt

@@ -0,0 +1,106 @@
+package com.iscs.comm
+
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.activity.enableEdgeToEdge
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.aspectRatio
+import androidx.compose.foundation.layout.fillMaxHeight
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.lazy.grid.GridCells
+import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
+import androidx.compose.foundation.lazy.grid.items
+import androidx.compose.material3.Card
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.unit.dp
+import com.iscs.comm.CommManager.write
+import com.iscs.comm.CommManager.writeByFrame
+import com.iscs.comm.entity.device.DeviceLockSlot
+import com.iscs.comm.entity.device.status.DeviceStatusLockSlot
+import com.iscs.comm.enums.DeviceType
+import com.iscs.comm.ui.theme.CommDemoTheme
+
+/**
+ * 打开控制页面Activity
+ */
+fun Context.openCtrlActivity(id: Int) {
+    startActivity(Intent(this, CtrlActivity::class.java).apply {
+        putExtra("cmd_id", id)
+    })
+}
+
+class CtrlActivity : ComponentActivity() {
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        enableEdgeToEdge()
+        setContent {
+            CommDemoTheme {
+                Scaffold(modifier = Modifier.fillMaxSize()) { pv ->
+                    BuildCtrlChild(pv)
+                }
+            }
+        }
+    }
+
+    /**
+     * 构建可以控制的子视图
+     */
+    @Composable
+    fun BuildCtrlChild(pv: PaddingValues) {
+        val cmd = intent.getIntExtra("cmd_id", -1)
+        val device = CommManager.deviceList.find { it.frame.cmd == cmd }
+        Box(modifier = Modifier.padding(10.dp, pv.calculateTopPadding())) {
+            when (device?.deviceType ?: DeviceType.NONE) {
+                DeviceType.SLOT_LOCK -> CtrlLock5(device!! as DeviceLockSlot)
+                // 未知设备
+                else -> Text("未知设备,无法控制")
+            }
+        }
+    }
+
+    @Composable
+    fun CtrlLock5(device: DeviceLockSlot) {
+        val status = device.deviceStatus as DeviceStatusLockSlot
+        LazyVerticalGrid(
+            columns = GridCells.Adaptive(minSize = 100.dp),
+            contentPadding = PaddingValues(10.dp, 10.dp),
+            horizontalArrangement = Arrangement.spacedBy(8.dp),
+            verticalArrangement = Arrangement.spacedBy(8.dp),
+        ) {
+            items(ArrayList(status.slotList.sortedBy { it.ch })) { state ->
+                Card(onClick = {
+                    state.isSlotLock = !state.isSlotLock
+                    device.ctrlSlotLock(state.ch, state.isSlotLock).writeByFrame()
+                }) {
+                    Column(
+                        modifier = Modifier
+                            .padding(10.dp)
+                            .aspectRatio(1.2f)
+                            .background(if (state.isUsed) Color.Blue else Color.Transparent)
+                            .fillMaxWidth(),
+                    ) {
+                        Text("${state.ch}路")
+                        Spacer(modifier = Modifier.fillMaxHeight())
+                        Text("是否上锁:${state.isSlotLock}")
+                    }
+                }
+            }
+
+        }
+    }
+}

+ 53 - 112
app/src/main/java/com/iscs/comm/MainActivity.kt

@@ -1,148 +1,89 @@
 package com.iscs.comm
 
 import android.os.Bundle
-import android.util.Log
 import androidx.activity.ComponentActivity
 import androidx.activity.compose.setContent
 import androidx.activity.enableEdgeToEdge
+import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.aspectRatio
 import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.width
-import androidx.compose.material3.Button
+import androidx.compose.foundation.lazy.grid.GridCells
+import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
+import androidx.compose.foundation.lazy.grid.items
+import androidx.compose.material3.Card
 import androidx.compose.material3.Scaffold
 import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.mutableStateListOf
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.unit.dp
-import androidx.lifecycle.lifecycleScope
+import androidx.compose.ui.unit.sp
 import com.iscs.comm.entity.device.Device
-import com.iscs.comm.entity.device.DeviceKeySlot
-import com.iscs.comm.entity.device.DeviceLockSlot
-import com.iscs.comm.entity.device.status.DeviceStatusKeySlot
-import com.iscs.comm.entity.device.status.DeviceStatusLockSlot
 import com.iscs.comm.intf.IDeviceListener
-import com.iscs.comm.ui.theme.CommunicationDemoTheme
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
+import com.iscs.comm.ui.theme.CommDemoTheme
 
 class MainActivity : ComponentActivity() {
 
-    private val list = ArrayList<Device>()
-
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         enableEdgeToEdge()
         setContent {
-            CommunicationDemoTheme {
-                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
-                    Column(modifier = Modifier.padding(10.dp)) {
-                        Text("测试锁底座", modifier = Modifier.padding(innerPadding))
-                        Row {
-                            Button({ ctrlLockSlotLock(0, false) }) { Text("0-开") }
-                            Spacer(modifier = Modifier.width(10.dp))
-                            Button({ ctrlLockSlotLock(0, true) }) { Text("0-关") }
-                            Spacer(modifier = Modifier.width(10.dp))
-                            Button({ ctrlLockSlotLock(1, false) }) { Text("1-开") }
-                            Spacer(modifier = Modifier.width(10.dp))
-                            Button({ ctrlLockSlotLock(1, true) }) { Text("1-关") }
-                            Spacer(modifier = Modifier.width(10.dp))
-                            Button({ ctrlLockSlotLock(2, false) }) { Text("2-开") }
-                            Spacer(modifier = Modifier.width(10.dp))
-                            Button({ ctrlLockSlotLock(2, true) }) { Text("2-关") }
-                        }
-                        Row {
-                            Button({ ctrlLockSlotLock(3, false) }) { Text("3-开") }
-                            Spacer(modifier = Modifier.width(10.dp))
-                            Button({ ctrlLockSlotLock(3, true) }) { Text("3-关") }
-                            Spacer(modifier = Modifier.width(10.dp))
-                            Button({ ctrlLockSlotLock(4, false) }) { Text("4-开") }
-                            Spacer(modifier = Modifier.width(10.dp))
-                            Button({ ctrlLockSlotLock(4, true) }) { Text("4-关") }
-                        }
-                        Text("测试钥匙底座", modifier = Modifier.padding(innerPadding))
-                        Row {
-                            Button({ ctrlKeySlotLock(0, false) }) { Text("0-开锁") }
-                            Spacer(modifier = Modifier.width(10.dp))
-                            Button({ ctrlKeySlotLock(0, true) }) { Text("0-关锁") }
-                            Spacer(modifier = Modifier.width(10.dp))
-                            Button({ ctrlKeySlotCharge(0, true) }) { Text("0-开充电") }
-                            Spacer(modifier = Modifier.width(10.dp))
-                            Button({ ctrlKeySlotCharge(0, false) }) { Text("0-关充电") }
-                            Spacer(modifier = Modifier.width(10.dp))
-                            Button({ ctrlKeyAllSlot(-1, false, false) }) { Text("全开关充电") }
-                        }
-                        Row {
-                            Button({ ctrlKeySlotLock(1, false) }) { Text("1-开锁") }
-                            Spacer(modifier = Modifier.width(10.dp))
-                            Button({ ctrlKeySlotLock(1, true) }) { Text("1-关锁") }
-                            Spacer(modifier = Modifier.width(10.dp))
-                            Button({ ctrlKeySlotCharge(1, true) }) { Text("1-开充电") }
-                            Spacer(modifier = Modifier.width(10.dp))
-                            Button({ ctrlKeySlotCharge(1, false) }) { Text("1-关充电") }
-                            Spacer(modifier = Modifier.width(10.dp))
-                            Button({ ctrlKeyAllSlot(-1, true, true) }) { Text("全关开充电") }
-                        }
-                    }
+            CommDemoTheme {
+                Scaffold(modifier = Modifier.fillMaxSize()) { pv ->
+                    buildDeviceList(pv)
                 }
             }
         }
-
-        // 做SDK初始化操作处理
-        initISCSSDK()
     }
 
-    fun ctrlLockSlotLock(ch: Int, isLock: Boolean) {
-        val device = list.find { it.frame.cmd == 0x0602 }
-        if (device is DeviceLockSlot) {
-            CommManager.write(device.ctrlSlotLock(ch, isLock))
-        }
-    }
+    @Composable
+    fun buildDeviceList(pv: PaddingValues) {
+        val list = mutableStateListOf<Device>()
+        val listener = object : IDeviceListener() {
 
-    fun ctrlKeySlotLock(ch: Int, isLock: Boolean) {
-        val device = list.find { it.frame.cmd == 0x0601 }
-        if (device is DeviceKeySlot) {
-            CommManager.write(device.ctrlSlotLock(ch, isLock))
-        }
-    }
-
-    fun ctrlKeySlotCharge(ch: Int, isCharge: Boolean) {
-        val device = list.find { it.frame.cmd == 0x0601 }
-        if (device is DeviceKeySlot) {
-            CommManager.write(device.ctrlSlotCharge(ch, isCharge))
-        }
-    }
+            override fun onDeviceList(devices: List<Device>) {
+                list.clear()
+                list.addAll(devices.sortedBy { it.frame.cmd })
+            }
 
-    fun ctrlKeyAllSlot(ch: Int, isLock: Boolean, isCharge: Boolean) {
-        val device = list.find { it.frame.cmd == 0x0601 }
-        if (device is DeviceKeySlot) {
-            CommManager.write(device.ctrlSlotLockAndCharge(ch, isLock, isCharge))
         }
-    }
-
-    /**
-     * 初始化ISCS SDK 操作
-     */
-    fun initISCSSDK() {
-        lifecycleScope.launch(Dispatchers.IO) {
+        LaunchedEffect("") {
+            // 设置设备变化监听
+            CommManager.addOnDeviceListener(listener)
+            // SDK初始化
             CommManager.init()
-            CommManager.setOnDeviceListener(object : IDeviceListener {
-
-                override fun onDeviceList(devices: List<Device>) {
-                    list.addAll(devices)
-                }
-
-                override fun onDeviceChanged(device: Device) {
-                    val msg = when (device.deviceStatus) {
-                        is DeviceStatusKeySlot -> (device.deviceStatus as DeviceStatusKeySlot).slotList.toString()
-                        is DeviceStatusLockSlot -> (device.deviceStatus as DeviceStatusLockSlot).slotList.toString()
-                        else -> "未知状态变化"
+        }
+        DisposableEffect("") {
+            // 移除页面监听
+            CommManager.removeOnDeviceListener(listener)
+            onDispose { }
+        }
+        LazyVerticalGrid(
+            columns = GridCells.Adaptive(minSize = 100.dp),
+            contentPadding = PaddingValues(10.dp, pv.calculateTopPadding() + 10.dp),
+            horizontalArrangement = Arrangement.spacedBy(8.dp),
+            verticalArrangement = Arrangement.spacedBy(8.dp),
+        ) {
+            items(list) { device ->
+                Card(onClick = { openCtrlActivity(device.frame.cmd) }) {
+                    Column(
+                        modifier = Modifier
+                            .padding(5.dp)
+                            .aspectRatio(1.2f)
+                            .fillMaxWidth()
+                    ) {
+                        Text(device.frame.cmd.toString(16))
+                        Text("${device.deviceType}", fontSize = 12.sp)
                     }
-                    Log.d("xiaoming", "设备状态发生变化了 $msg")
                 }
-
-            })
+            }
         }
+
     }
 }

+ 1 - 1
app/src/main/java/com/iscs/comm/ui/theme/Theme.kt

@@ -33,7 +33,7 @@ private val LightColorScheme = lightColorScheme(
 )
 
 @Composable
-fun CommunicationDemoTheme(
+fun CommDemoTheme(
     darkTheme: Boolean = isSystemInDarkTheme(),
     // Dynamic color is available on Android 12+
     dynamicColor: Boolean = true,

+ 22 - 6
transport/src/main/java/com/iscs/comm/CommManager.kt

@@ -25,10 +25,10 @@ object CommManager {
     private var manager: AbsCommBase? = null
 
     // 用于存储通信后获取到的设备列表,支持高并发
-    private val deviceList = ConcurrentLinkedQueue<Device>()
+    val deviceList = ConcurrentLinkedQueue<Device>()
 
     // 设备变化监听
-    private var deviceListener: IDeviceListener? = null
+    private val deviceChangeListeners = ConcurrentLinkedQueue<IDeviceListener>()
 
     fun init() {
         // 初始化前释放资源
@@ -53,8 +53,15 @@ object CommManager {
     /**
      * 设置设备变化监听
      */
-    fun setOnDeviceListener(listener: IDeviceListener) {
-        this.deviceListener = listener
+    fun addOnDeviceListener(listener: IDeviceListener) {
+        this.deviceChangeListeners.add(listener)
+    }
+
+    /**
+     * 移除一个设备监听
+     */
+    fun removeOnDeviceListener(listener: IDeviceListener) {
+        this.deviceChangeListeners.remove(listener)
     }
 
     /**
@@ -66,6 +73,13 @@ object CommManager {
         manager?.write(frame)
     }
 
+    /**
+     * 根据命令Frame去下发控制命令
+     */
+    fun Frame.writeByFrame() = manager?.scope?.launch {
+        manager?.write(this@writeByFrame)
+    }
+
     /**
      * 发送数据帧,带响应
      *
@@ -81,6 +95,7 @@ object CommManager {
     private fun initDeviceList() = manager?.scope?.launch {
         val frames = Frame().buildReadDeviceInfo()
         deviceList.clear()
+        delay(1000)
         frames.forEach {
             // 遍历CAN口,看有哪些设备存在
             val frame = writeWithResponse(it)
@@ -91,7 +106,8 @@ object CommManager {
         // 遍历一遍设备状态
         checkDeviceStatus(true)?.join()
         // 将设备列表回调给外部
-        deviceListener?.onDeviceList(ArrayList(deviceList))
+        deviceChangeListeners.forEach { it.onDeviceList(ArrayList(deviceList)) }
+        // 延时一点时间,开始执行查询设备状态操作
         delay(20)
         // 开启轮询设备状态
         startDeviceStatusLoop()
@@ -121,7 +137,7 @@ object CommManager {
             val sFrame = writeWithResponse(it.ctrlCheckDeviceStatus())
             it.updateDeviceStatus(sFrame)
             // 设备状态发生变化通知外部
-            if (it.isDeviceStatusChanged() && !isInit) deviceListener?.onDeviceChanged(it)
+            if (it.isDeviceStatusChanged() && !isInit) deviceChangeListeners.forEach { lis -> lis.onDeviceChanged(it) }
             // 限制轮询的速度
             delay(50)
         }

+ 2 - 2
transport/src/main/java/com/iscs/comm/entity/device/Device.kt

@@ -4,7 +4,7 @@ import com.iscs.comm.entity.Frame
 import com.iscs.comm.entity.device.status.DeviceStatus
 import com.iscs.comm.entity.device.status.DeviceStatusNone
 import com.iscs.comm.enums.DeviceType
-import com.iscs.comm.extension.buildCtrlKeySlotStatus
+import com.iscs.comm.extension.buildCtrlReadDeviceStatus
 
 /**
  * 用于封装设备类型对外输出
@@ -43,7 +43,7 @@ abstract class Device(val frame: Frame) {
      * 问题:如果是钥匙仓位的话,开启充电时仓位是否有设备就不上报了
      */
     open fun ctrlCheckDeviceInfo(): Frame {
-        return frame.newFrame().apply { cmd = frame.cmd }.buildCtrlKeySlotStatus()
+        return frame.newFrame().apply { cmd = frame.cmd }.buildCtrlReadDeviceStatus()
     }
 
     /**

+ 2 - 2
transport/src/main/java/com/iscs/comm/entity/device/DeviceKeySlot.kt

@@ -4,7 +4,7 @@ import com.iscs.comm.entity.Frame
 import com.iscs.comm.entity.device.status.DeviceStatus
 import com.iscs.comm.entity.device.status.DeviceStatusKeySlot
 import com.iscs.comm.enums.DeviceType
-import com.iscs.comm.extension.buildCheckDeviceStatus
+import com.iscs.comm.extension.buildCheckDeviceCtrlStatus
 import com.iscs.comm.extension.buildCtrlKeySlotLockAndCharge
 
 /**
@@ -26,7 +26,7 @@ class DeviceKeySlot(frame: Frame) : Device(frame) {
      * 构建获取钥匙锁定状态的数据帧
      */
     override fun ctrlCheckDeviceStatus(): Frame {
-        return frame.newFrame().apply { cmd = frame.cmd }.buildCheckDeviceStatus()
+        return frame.newFrame().apply { cmd = frame.cmd }.buildCheckDeviceCtrlStatus()
     }
 
     /**

+ 2 - 3
transport/src/main/java/com/iscs/comm/entity/device/DeviceLockSlot.kt

@@ -2,10 +2,9 @@ package com.iscs.comm.entity.device
 
 import com.iscs.comm.entity.Frame
 import com.iscs.comm.entity.device.status.DeviceStatus
-import com.iscs.comm.entity.device.status.DeviceStatusKeySlot
 import com.iscs.comm.entity.device.status.DeviceStatusLockSlot
 import com.iscs.comm.enums.DeviceType
-import com.iscs.comm.extension.buildCheckDeviceStatus
+import com.iscs.comm.extension.buildCheckDeviceCtrlStatus
 import com.iscs.comm.extension.buildCtrlLockSlotLock
 
 /**
@@ -25,7 +24,7 @@ class DeviceLockSlot(frame: Frame) : Device(frame) {
     override var deviceStatus: DeviceStatus = DeviceStatusLockSlot()
 
     override fun ctrlCheckDeviceStatus(): Frame {
-        return frame.newFrame().apply { cmd = frame.cmd }.buildCheckDeviceStatus()
+        return frame.newFrame().apply { cmd = frame.cmd }.buildCheckDeviceCtrlStatus()
     }
 
     /**

+ 2 - 2
transport/src/main/java/com/iscs/comm/entity/device/DeviceNone.kt

@@ -1,7 +1,7 @@
 package com.iscs.comm.entity.device
 
 import com.iscs.comm.entity.Frame
-import com.iscs.comm.extension.buildCheckDeviceStatus
+import com.iscs.comm.extension.buildCheckDeviceCtrlStatus
 
 /**
  * 未知设备类型
@@ -21,7 +21,7 @@ class DeviceNone(frame: Frame) : Device(frame) {
     }
 
     override fun ctrlCheckDeviceStatus(): Frame {
-        return frame.newFrame().apply { cmd = frame.cmd }.buildCheckDeviceStatus()
+        return frame.newFrame().apply { cmd = frame.cmd }.buildCheckDeviceCtrlStatus()
     }
 
 }

+ 32 - 0
transport/src/main/java/com/iscs/comm/entity/device/DeviceSupplyCabinet.kt

@@ -0,0 +1,32 @@
+package com.iscs.comm.entity.device
+
+import com.iscs.comm.entity.Frame
+import com.iscs.comm.enums.DeviceType
+import com.iscs.comm.extension.buildCheckDeviceCtrlStatus
+import com.iscs.comm.extension.toHexString
+import com.iscs.comm.utils.ISCSLog
+
+/**
+ * 物资柜主板
+ */
+class DeviceSupplyCabinet(frame: Frame) : Device(frame) {
+
+    override val deviceType: DeviceType = DeviceType.SUPPLY_CABINET
+
+
+    override fun ctrlCheckDeviceStatus(): Frame {
+        return frame.newFrame().apply { cmd = frame.cmd }.buildCheckDeviceCtrlStatus()
+    }
+
+    override fun updateDeviceInfo(frame: Frame) {
+        // ISCSLog.i("xiaoming", "更新设备信息:${frame.data.toHexString()}")
+    }
+
+    override fun updateDeviceStatus(frame: Frame) {
+        // ISCSLog.i("xiaoming", "更新设备状态:${frame.data.toHexString()}")
+    }
+
+    override fun isDeviceStatusChanged(): Boolean {
+        return false
+    }
+}

+ 4 - 3
transport/src/main/java/com/iscs/comm/enums/DeviceType.kt

@@ -1,7 +1,8 @@
 package com.iscs.comm.enums
 
 enum class DeviceType {
-    NONE,
-    SLOT_KEY,
-    SLOT_LOCK,
+    NONE,           // 未知
+    SLOT_KEY,       // 2路钥匙底座
+    SLOT_LOCK,      // 5路锁底座
+    SUPPLY_CABINET, // 物资柜
 }

+ 4 - 5
transport/src/main/java/com/iscs/comm/extension/CommFrameExt.kt

@@ -8,7 +8,6 @@ import com.iscs.comm.protocol.CanProtocol.CAN_READ_CMD
 import com.iscs.comm.protocol.CanProtocol.CAN_WRITE_CMD_2BYTE
 import com.iscs.comm.utils.ISCSLog
 
-
 /**
  * 构建读CAN总线下设备信息命令集合
  */
@@ -24,9 +23,9 @@ fun Frame.buildReadDeviceInfo(): List<Frame> {
 }
 
 /**
- * 构建读设备信息命令
+ * 构建用于读设备控制信息命令
  */
-fun Frame.buildCheckDeviceStatus(): Frame {
+fun Frame.buildCheckDeviceCtrlStatus(): Frame {
     data = byteArrayOf(
         CAN_READ_CMD.toByte(), (CAN_KEY_RW and 0xFF).toByte(), ((CAN_KEY_RW shr 8) and 0xFF).toByte(), 0x00,
         0x00, 0x00, 0x00, 0x00
@@ -68,9 +67,9 @@ fun Frame.buildCtrlKeySlotLockAndCharge(ch: Int, isLock: Boolean, isCharge: Bool
 }
 
 /**
- * 查询钥匙底座状态
+ * 构建查询设备信息状态的命令
  */
-fun Frame.buildCtrlKeySlotStatus(): Frame {
+fun Frame.buildCtrlReadDeviceStatus(): Frame {
     val id = this.cmd
     return this.newFrame().apply {
         cmd = id

+ 3 - 0
transport/src/main/java/com/iscs/comm/extension/DeviceFactoryExt.kt

@@ -2,6 +2,7 @@ package com.iscs.comm.extension
 
 import com.iscs.comm.entity.Frame
 import com.iscs.comm.entity.device.Device
+import com.iscs.comm.entity.device.DeviceSupplyCabinet
 import com.iscs.comm.entity.device.DeviceNone
 import com.iscs.comm.entity.device.DeviceKeySlot
 import com.iscs.comm.entity.device.DeviceLockSlot
@@ -18,6 +19,8 @@ fun Frame.factoryDevice(): Device {
         0 -> DeviceKeySlot(this)
         // 5路挂锁底座
         1 -> DeviceLockSlot(this)
+        // 物资柜主板
+        3 -> DeviceSupplyCabinet(this)
         // 其余未知设备
         else -> DeviceNone(this)
     }

+ 3 - 3
transport/src/main/java/com/iscs/comm/intf/IDeviceListener.kt

@@ -2,20 +2,20 @@ package com.iscs.comm.intf
 
 import com.iscs.comm.entity.device.Device
 
-interface IDeviceListener {
+abstract class IDeviceListener {
 
     /**
      * 回调所有设备列表
      *
      * @param devices 回调的设备列表
      */
-    fun onDeviceList(devices: List<Device>)
+    open fun onDeviceList(devices: List<Device>) {}
 
     /**
      * 回调设备变化了监听
      *
      * @param device
      */
-    fun onDeviceChanged(device: Device)
+    open fun onDeviceChanged(device: Device) {}
 
 }