|
|
@@ -28,15 +28,82 @@ object CanCommands {
|
|
|
WRITE_ERROR = 0x80
|
|
|
)
|
|
|
|
|
|
+ /**
|
|
|
+ * 指令 主索引
|
|
|
+ */
|
|
|
+ object Command {
|
|
|
+ /**
|
|
|
+ * 设备类型
|
|
|
+ */
|
|
|
+ const val DEVICE_TYPE = 0x6000
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 版本号
|
|
|
+ */
|
|
|
+ const val VERSION = 0x6003
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 状态
|
|
|
+ */
|
|
|
+ const val STATUS = 0x6010
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 控制状态
|
|
|
+ */
|
|
|
+ const val CONTROL_REG = 0x6011
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 物资柜存储状态
|
|
|
+ */
|
|
|
+ const val STORAGE_REG = 0x6012
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 照明/消毒
|
|
|
+ */
|
|
|
+ const val LIGHT_REG = 0x6015
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 灯带控制
|
|
|
+ */
|
|
|
+ const val LED_STRIP_CONTROL = 0x6016
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 温度
|
|
|
+ */
|
|
|
+ const val TEMPERATURE = 0x6017
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 湿度
|
|
|
+ */
|
|
|
+ const val HUMIDITY = 0x6018
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 左钥匙rfid/挂锁RFID/钥匙柜RFID
|
|
|
+ */
|
|
|
+ const val RFID = 0x6020
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 右钥匙RFID
|
|
|
+ */
|
|
|
+ const val RIGHT_KEY_RFID = 0x6024
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
// ========= 通用区:所有节点都能用 =========
|
|
|
object Common {
|
|
|
/** 版本 (R) → 0x6003/0x00, 4B: HW主,HW子,SW主,SW子 */
|
|
|
fun getDeviceVersion(nodeId: Int): SdoRequest.Read =
|
|
|
- SdoRequest.Read(nodeId, 0x6003, 0x00)
|
|
|
+ SdoRequest.Read(nodeId, Command.VERSION, 0x00)
|
|
|
|
|
|
/** 大多数设备复用的状态寄存器 (R) → 0x6010/0x00, 2B */
|
|
|
fun getStatus(nodeId: Int): SdoRequest.Read =
|
|
|
- SdoRequest.Read(nodeId, 0x6010, 0x00)
|
|
|
+ SdoRequest.Read(nodeId, Command.STATUS, 0x00)
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取设备类型
|
|
|
+ */
|
|
|
+ fun getDeviceType(nodeId: Int): SdoRequest.Read =
|
|
|
+ SdoRequest.Read(nodeId, Command.DEVICE_TYPE, 0x00)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -51,14 +118,14 @@ object CanCommands {
|
|
|
|
|
|
/** 控制/状态 (R/W) 0x6011/0x00, 2B:写仅置相关位,其余写0;读回含工作位 */
|
|
|
fun readControlReg(): SdoRequest.Read =
|
|
|
- SdoRequest.Read(nodeId, 0x6011, 0x00)
|
|
|
+ SdoRequest.Read(nodeId, Command.CONTROL_REG, 0x00)
|
|
|
|
|
|
/** 设置左右卡扣(bit0=左卡扣,bit4=右卡扣) */
|
|
|
fun setLatch(left: Boolean? = null, right: Boolean? = null): SdoRequest.Write {
|
|
|
var v = 0
|
|
|
if (left != null) v = v or ((if (left) 1 else 0) shl 0)
|
|
|
if (right != null) v = v or ((if (right) 1 else 0) shl 4)
|
|
|
- return SdoRequest.Write(nodeId, 0x6011, 0x00, shortLE(0b0001_0001, v), 2)
|
|
|
+ return SdoRequest.Write(nodeId, Command.CONTROL_REG, 0x00, shortLE(v, 0b0001_0001), 2)
|
|
|
}
|
|
|
|
|
|
/** 设置左右充电(bit1=左充电,bit5=右充电) */
|
|
|
@@ -66,7 +133,7 @@ object CanCommands {
|
|
|
var v = 0
|
|
|
if (leftOn != null) v = v or ((if (leftOn) 1 else 0) shl 1)
|
|
|
if (rightOn != null) v = v or ((if (rightOn) 1 else 0) shl 5)
|
|
|
- return SdoRequest.Write(nodeId, 0x6011, 0x00, shortLE(0b0010_0010, v), 2)
|
|
|
+ return SdoRequest.Write(nodeId, Command.CONTROL_REG, 0x00, shortLE(v, 0b0010_0010), 2)
|
|
|
}
|
|
|
|
|
|
/** 单侧卡扣语法糖:keySlotId: 0左/1右;status: 0解锁/1锁住 */
|
|
|
@@ -76,42 +143,48 @@ object CanCommands {
|
|
|
val bit = if (keySlotId == 0) 0 else 4
|
|
|
return SdoRequest.Write(
|
|
|
nodeId,
|
|
|
- 0x6011,
|
|
|
+ Command.CONTROL_REG,
|
|
|
0x00,
|
|
|
- shortLE(1 shl bit, (status and 1) shl bit),
|
|
|
+ shortLE((status and 1) shl bit, 1 shl bit),
|
|
|
2
|
|
|
)
|
|
|
}
|
|
|
|
|
|
/** 左/右 RFID (R) 4B 小端(常见地址) */
|
|
|
- fun getLeftRfid(): SdoRequest.Read = SdoRequest.Read(nodeId, 0x6020, 0x00)
|
|
|
- fun getRightRfid(): SdoRequest.Read = SdoRequest.Read(nodeId, 0x6024, 0x00)
|
|
|
+ fun getLeftRfid(): SdoRequest.Read = SdoRequest.Read(nodeId, Command.RFID, 0x00)
|
|
|
+ fun getRightRfid(): SdoRequest.Read = SdoRequest.Read(nodeId, Command.RIGHT_KEY_RFID, 0x00)
|
|
|
|
|
|
// ---- FiveLock / KeyCabinet(常见 1..5 位同构写法,寄存器通常与 0x6011 兼容) ----
|
|
|
|
|
|
/** 一次写入 5 位控制(低5位有效),适配 5路/柜体同构 */
|
|
|
fun setLatchBits_1to5(bits01to05: Int): SdoRequest.Write {
|
|
|
val v = bits01to05 and 0b1_1111
|
|
|
- return SdoRequest.Write(nodeId, 0x6011, 0x00, shortLE(0b1_1111, v), 2)
|
|
|
+ return SdoRequest.Write(nodeId, Command.CONTROL_REG, 0x00, shortLE(v, 0b1_1111), 2)
|
|
|
}
|
|
|
|
|
|
/** 单位控制(1..5) */
|
|
|
fun controlOne_1to5(slotIndex1to5: Int, locked: Boolean): SdoRequest.Write {
|
|
|
require(slotIndex1to5 in 1..5) { "slotIndex must be 1..5" }
|
|
|
val v = (if (locked) 1 else 0) shl (slotIndex1to5 - 1)
|
|
|
- return SdoRequest.Write(nodeId, 0x6011, 0x00, shortLE(1 shl (slotIndex1to5 - 1), v), 2)
|
|
|
+ return SdoRequest.Write(
|
|
|
+ nodeId,
|
|
|
+ Command.CONTROL_REG,
|
|
|
+ 0x00,
|
|
|
+ shortLE(v, 1 shl (slotIndex1to5 - 1)),
|
|
|
+ 2
|
|
|
+ )
|
|
|
}
|
|
|
|
|
|
/** 1..5 位 RFID 常见映射:0x6020..0x6024 */
|
|
|
fun getSlotRfid_1to5(slotIndex1to5: Int): SdoRequest.Read {
|
|
|
require(slotIndex1to5 in 1..5) { "slotIndex must be 1..5" }
|
|
|
- return SdoRequest.Read(nodeId, 0x6020 + (slotIndex1to5 - 1), 0x00)
|
|
|
+ return SdoRequest.Read(nodeId, Command.RFID, 0x00 + (slotIndex1to5 - 1))
|
|
|
}
|
|
|
|
|
|
// ---- MaterialCabinet(RGB/温湿度扩展) ----
|
|
|
|
|
|
/** RGB 状态灯 (R/W) 0x6016/0x00, 4B: B[0..7],G[8..15],R[16..23], 模式[24..26], 时间[27..29], 单位[30], 锁定[31] */
|
|
|
- fun getRgb(): SdoRequest.Read = SdoRequest.Read(nodeId, 0x6016, 0x00)
|
|
|
+ fun getRgb(): SdoRequest.Read = SdoRequest.Read(nodeId, Command.LED_STRIP_CONTROL, 0x00)
|
|
|
|
|
|
fun setRgb(
|
|
|
r: Int, g: Int, b: Int, // 0..255
|
|
|
@@ -133,12 +206,12 @@ object CanCommands {
|
|
|
v = v or ((tt and 0x07) shl 27)
|
|
|
v = v or ((if (secondsUnit) 1 else 0) shl 30)
|
|
|
v = v or ((if (lockControl) 1 else 0) shl 31)
|
|
|
- return SdoRequest.Write(nodeId, 0x6016, 0x00, intLE(v), 4)
|
|
|
+ return SdoRequest.Write(nodeId, Command.LED_STRIP_CONTROL, 0x00, intLE(v), 4)
|
|
|
}
|
|
|
|
|
|
/** 温湿度(常见扩展) */
|
|
|
- fun getTemperature(): SdoRequest.Read = SdoRequest.Read(nodeId, 0x6017, 0x00)
|
|
|
- fun getHumidity(): SdoRequest.Read = SdoRequest.Read(nodeId, 0x6018, 0x00)
|
|
|
+ fun getTemperature(): SdoRequest.Read = SdoRequest.Read(nodeId, Command.TEMPERATURE, 0x00)
|
|
|
+ fun getHumidity(): SdoRequest.Read = SdoRequest.Read(nodeId, Command.HUMIDITY, 0x00)
|
|
|
|
|
|
// ---- 通用状态 ----
|
|
|
fun getStatus(): SdoRequest.Read = Common.getStatus(nodeId)
|
|
|
@@ -147,7 +220,7 @@ object CanCommands {
|
|
|
|
|
|
// ========= Byte 打包工具(LE) =========
|
|
|
private fun shortLE(control: Int, target: Int): ByteArray =
|
|
|
- byteArrayOf((target and 0xFF).toByte(), (control and 0xFF).toByte())
|
|
|
+ byteArrayOf((control and 0xFF).toByte(), (target and 0xFF).toByte())
|
|
|
|
|
|
private fun intLE(v: Int): ByteArray = byteArrayOf(
|
|
|
(v and 0xFF).toByte(),
|