package com.grkj.iscs.modbus import android.content.Context import com.grkj.iscs.extentions.removeLeadingZeros import com.grkj.iscs.extentions.toHexStrings import com.grkj.iscs.model.DeviceConst.DOCK_TYPE_ELEC_LOCK_BOARD import com.grkj.iscs.model.DeviceConst.DOCK_TYPE_KEY import com.grkj.iscs.model.DeviceConst.DOCK_TYPE_LOCK import com.grkj.iscs.model.DeviceConst.DOCK_TYPE_PORTABLE import com.grkj.iscs.util.Executor import com.grkj.iscs.util.log.LogUtil import java.util.concurrent.Executors /** * ModBus 主控板控制器 */ object ModBusController { /** * 底座列表 */ var dockList: MutableList = mutableListOf() private const val LISTENER_TYPE_STATUS = 3 // 主控板管理器 private var modBusManager: ModBusManager? = null private var slaveCount: Int = 0 private val threadPool = Executors.newScheduledThreadPool(4) private val listeners = ArrayList() // 是否中断读取状态 private var interruptReadStatus: ArrayList = ArrayList() var shouldStopUpgrade = false fun setSlaveCount(count: Int) { modBusManager?.slaveCount = count slaveCount = count } class StatusListener( val key: Any, val listener: (Any) -> Unit, val type: Int ) fun interruptReadTrashBinStatus(interrupt: Boolean) { interruptReadStatus.clear() interruptReadStatus.add(interrupt) } @ExperimentalUnsignedTypes fun start(ctx: Context) { modBusManager?.stop() PortManager.openCtrlBord(ctx) ?.let { pm -> return@let ModBusManager(slaveCount, pm, true) } // 间隔 1 秒读一遍桶的状态 ?.repeatSendToAll(MBFrame.READ_STATUS, { interruptReadStatus }, { res -> // // Logger.d("ModbusController", "res: ${res.map { it.toHexString() }}") LogUtil.i("****************************************************************************") for (l in listeners) { if (l.type == LISTENER_TYPE_STATUS) { l.listener(res) } } // TODO 临时改成5s // }, 1000) }, 5000) ?.also { modBusManager = it Executor.runOnIO { // refreshAllowOpenDoorUnidentified(ctx, it) } } ?.start() } fun registerStatusListener(key: Any, listener: (Any) -> Unit) { listeners.add(StatusListener(key, listener, LISTENER_TYPE_STATUS)) } fun unregisterListener(key: Any) { val it = listeners.iterator() while (it.hasNext()) { if (it.next().key == key) { it.remove() } } } fun stop() { modBusManager?.stop() } /*****************************************************************************************/ /** * 初始化所有设备的状态 */ // TODO 通电后多久执行?App每次重启的执行是什么 fun initDevicesStatus() { readDeviceType { res -> res.forEach { bytes -> if (bytes.size < 5) return@forEach // TODO 设备具体数据由0x0011寄存器提供 updateDeviceType(bytes[0], bytes[4]) val type = when (bytes[4]) { DOCK_TYPE_KEY -> "钥匙底座" DOCK_TYPE_LOCK -> "锁具底座" DOCK_TYPE_ELEC_LOCK_BOARD -> "电磁锁控制板" DOCK_TYPE_PORTABLE -> "便携式底座" else -> "未知" } LogUtil.i("initDevicesStatus 设备(${bytes[0].toInt()})类型:$type") } } Executor.delayOnMain({ // TODO 待完善 initLock() // TODO 打开所有无锁的卡扣、读取所有锁的RFID initKey() // TODO 打开所有无钥匙的卡扣、关闭所有钥匙灯光、读取所有钥匙的RFID // TODO 设置所有钥匙的模式 // TODO 通过HTTP获取所有钥匙的Mac }, 3000) } /** * 初始化锁具——打开所有无锁的卡扣、读取RFID */ private fun initLock() { LogUtil.i("initLock : $dockList") dockList.filter { it.type == DOCK_TYPE_LOCK }.forEach { dockBean -> val hasLockIdxList = dockBean.getLockList().filter { it.isExist }.map { it.idx } val noLockIdxList = dockBean.getLockList().filter { !it.isExist }.map { it.idx } as MutableList hasLockIdxList.forEach { idx -> readLockRfid(dockBean.addr.toInt() - 1, idx) { res -> val rfid = res.copyOfRange(3, 11).toHexStrings(false).removeLeadingZeros() LogUtil.i("初始化锁具 RFID : $rfid") updateLockRfid(dockBean.addr.toInt(), idx, rfid) } } controlLockBuckle(true, dockBean.addr.toInt() - 1, noLockIdxList) } } /** * 初始化钥匙——关闭所有钥匙灯光 */ private fun initKey() { LogUtil.i("initKey : $dockList") dockList.filter { it.type == DOCK_TYPE_KEY }.forEach { dockBean -> controlKeyLight(dockBean.addr.toInt() - 1, 2, 2) dockBean.getKeyList().forEach { key -> if (key.isExist) { LogUtil.i("initKey : ${dockBean.addr.toInt() - 1} : ${key.isLeft}") readKeyRfid(dockBean.addr.toInt() - 1, key.isLeft) { isLeft, res -> val rfid = res.copyOfRange(3, 11).toHexStrings(false).removeLeadingZeros() LogUtil.i("初始化钥匙 RFID : $rfid") updateKeyRfid(dockBean.addr.toInt(), isLeft, rfid) } } else { // TODO 关闭钥匙卡扣 } } } } /** * 更新状态 */ fun updateStatus(byteArray: ByteArray): DockBean? { if (byteArray.isEmpty()) { return null } val dockB = dockList.find { it.addr == byteArray[0] } return dockB?.parseStatus(byteArray) ?: let { val temp = DockBean(byteArray[0], null, mutableListOf()) dockList.add(temp) temp.parseStatus(byteArray) } } /** * 读取设备类型 */ fun readDeviceType(done: ((res: List) -> Unit)? = null) { modBusManager?.sendToAll(MBFrame.READ_DEVICE_TYPE) { res -> done?.invoke(res) } } /** * 更新设备类型 */ fun updateDeviceType(idx: Byte?, type: Byte?) { dockList.find { it.addr == idx }?.type = type } /** * 读取卡扣状态 * * @param isLock true:读锁具底座 false:读钥匙底座 * @param type 0:钥匙底座 1:锁具底座1-8 2:锁具底座9、10 */ fun readBuckleStatus(isLock: Boolean, slaveIdx: Int?, doneSingle: ((type: Int, res: ByteArray) -> Unit)? = null) { // TODO 电磁锁控制板可能不是,并且锁和钥匙的读取不一样 slaveIdx?.let { modBusManager?.sendTo(it, MBFrame.READ_BUCKLE_STATUS) { res -> doneSingle?.invoke(if (isLock) 1 else 0, res) } if (isLock) { modBusManager?.sendTo(it, MBFrame.READ_LOCK_BUCKLE_EXTRA_STATUS) { res -> doneSingle?.invoke(2, res) } } } } /** * 开/关锁具卡扣 */ fun controlLockBuckle(isOpen: Boolean, slaveIdx: Int?, lockIdx: Int, done: ((res: ByteArray) -> Unit)? = null) { slaveIdx?.let { modBusManager?.generateLockBuckleCmd(isOpen, lockIdx)?.let { cmd -> modBusManager?.sendTo(it, cmd) { res -> done?.invoke(res) } } } } fun controlLockBuckle(isOpen: Boolean, slaveIdx: Int?, lockIdxList: MutableList, done: ((res: ByteArray) -> Unit)? = null) { slaveIdx?.let { modBusManager?.generateLockBuckleCmd(isOpen, lockIdxList)?.let { cmdList -> cmdList.forEach { cmd -> modBusManager?.sendTo(it, cmd) { res -> done?.invoke(res) } } } } } /** * 读取钥匙RFID */ fun readKeyRfid(slaveIdx: Int?, isLeft: Boolean, done: ((isLeft: Boolean, res: ByteArray) -> Unit)? = null) { slaveIdx?.let { modBusManager?.generateRfidCmd(if (isLeft) 0 else 1)?.let { cmd -> modBusManager?.sendTo(it, cmd) { done?.invoke(isLeft, it) } } } } /** * 读取锁具RFID */ fun readLockRfid(slaveIdx: Int?, lockIdx: Int, done: ((res: ByteArray) -> Unit)? = null) { slaveIdx?.let { modBusManager?.generateRfidCmd(lockIdx)?.let { cmd -> modBusManager?.sendTo(it, cmd) { res -> done?.invoke(res) } } } } /** * 更新钥匙RFID */ fun updateKeyRfid(slaveIdx: Int, isLeft: Boolean, rfid: String) { dockList.find { it.addr.toInt() == slaveIdx }?.getKeyList()?.find { it.isLeft == isLeft }?.rfid = rfid } /** * 通过RFID更新对应的Mac */ fun updateKeyMacByRfid(rfid: String, mac: String) { dockList.find { it.type == DOCK_TYPE_KEY }?.getKeyList()?.find { it.rfid == rfid }?.mac = mac } /** * 更新锁具RFID */ fun updateLockRfid(slaveIdx: Int, lockIdx: Int, rfid: String) { dockList.find { it.addr.toInt() == slaveIdx }?.getLockList()?.find { it.idx == lockIdx }?.rfid = rfid } /** * 操作钥匙灯 * * @param leftAction、rightAction 0:保持当前状态 1:点亮 2:熄灭 默认0 */ fun controlKeyLight(slaveIdx: Int?, leftAction: Int = 0, rightAction: Int = 0, done: ((res: ByteArray) -> Unit)? = null) { slaveIdx?.let { modBusManager?.generateKeyLightCmd(leftAction, rightAction)?.let { cmd -> modBusManager?.sendTo(it, cmd) { done?.invoke(it) } } } } /** * 开/关钥匙卡扣 * * @param isOpen true:开操作 false:关操作 * @param isLeft true:左卡扣 false:右卡扣 */ fun controlKeyBuckle(isOpen: Boolean, isLeft: Boolean, slaveIdx: Int?, done: ((res: ByteArray) -> Unit)? = null) { slaveIdx?.let { modBusManager?.generateKeyBuckleCmd(isOpen, if (isLeft) 0 else 1)?.let { cmd -> modBusManager?.sendTo(it, cmd) { res -> done?.invoke(res) } } } } /** * 根据RFID找钥匙 */ fun getKeyByRfid(rfid: String): DockBean.KeyBean? { return dockList.find { it.type == DOCK_TYPE_KEY }?.getKeyList()?.find { it.rfid == rfid } } /** * 根据RFID找锁具 */ fun getLockByRfid(rfid: String): DockBean.LockBean? { return dockList.find { it.type == DOCK_TYPE_LOCK }?.getLockList()?.find { it.rfid == rfid } } }