| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016 |
- package com.grkj.iscs.modbus
- import android.content.Context
- import com.clj.fastble.BleManager
- import com.grkj.iscs.BusinessManager
- import com.grkj.iscs.BusinessManager.CAN_RETURN
- import com.grkj.iscs.R
- import com.grkj.iscs.extentions.removeLeadingZeros
- import com.grkj.iscs.extentions.toHexStrings
- import com.grkj.iscs.model.DeviceConst.DEVICE_TYPE_CARD
- import com.grkj.iscs.model.DeviceConst.DEVICE_TYPE_FINGERPRINT
- import com.grkj.iscs.model.DeviceConst.DEVICE_TYPE_KEY
- import com.grkj.iscs.model.DeviceConst.DEVICE_TYPE_LOCK
- import com.grkj.iscs.model.DeviceConst.DOCK_TYPE_COLLECT
- 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.model.vo.hardware.CabinetSlotsRecord
- import com.grkj.iscs.util.CommonUtils
- import com.grkj.iscs.util.Executor
- import com.grkj.iscs.util.NetApi
- import com.grkj.iscs.util.ToastUtils
- import com.grkj.iscs.util.log.LogUtil
- import java.util.concurrent.atomic.AtomicInteger
- import java.util.stream.Collectors
- /**
- * ModBus 主控板控制器
- */
- object ModBusController {
- /**
- * 是否初始化完成
- */
- var isInitReady = false
- /**
- * 底座列表
- */
- var dockList: MutableList<DockBean> = mutableListOf()
- /**
- * 监听状态类型
- */
- private const val LISTENER_TYPE_STATUS = 3
- // 主控板管理器
- var modBusManager: ModBusManager? = null
- /**
- * 监听器
- */
- private val listeners = ArrayList<StatusListener>()
- // 是否中断读取状态
- private var interruptReadStatus: ArrayList<Boolean> = ArrayList()
- /**
- * 重复时间
- */
- // TODO 临时改成5s
- const val REPEAT_FREQUENCY = 800L
- /**
- * 中断读取
- */
- fun interruptReadTrashBinStatus(interrupt: Boolean) {
- interruptReadStatus.clear()
- interruptReadStatus.add(interrupt)
- }
- /**
- * 启动通信引擎
- */
- @ExperimentalUnsignedTypes
- fun start(ctx: Context) {
- modBusManager?.stop()
- PortManager.openCtrlBord(ctx)?.let { pm ->
- return@let ModBusManager(pm, true)
- }
- // 间隔 1 秒读一遍桶的状态
- ?.repeatSendToAll(MBFrame.READ_STATUS, {
- interruptReadStatus
- }, { res ->
- LogUtil.i("****************************************************************************")
- // 过滤非空的数据,重置slaveCount
- // 不再使用slaveCount,改用地址池
- for (l in listeners) {
- if (l.type == LISTENER_TYPE_STATUS) {
- l.listener(res)
- }
- }
- }, REPEAT_FREQUENCY)?.also {
- modBusManager = 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()
- }
- /**
- * 引擎是否运行中
- */
- fun isRunning(): Boolean? {
- return modBusManager?.isRunning()
- }
- /*****************************************************************************************/
- /**
- * 初始化所有设备的状态
- */
- fun initDevicesStatus() {
- readDeviceType { res ->
- res.forEach { bytes ->
- if (bytes.size < 5) return@forEach
- // 设备具体数据由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 -> "便携式底座"
- DOCK_TYPE_COLLECT -> "开关量采集板"
- else -> "未知"
- }
- LogUtil.i("initDevicesStatus 设备(${bytes[0].toInt()})类型:$type")
- }
- // TODO 待完善
- Executor.repeatOnMain({
- if (isInitReady) {
- initLock() // 打开所有无锁的卡扣、关闭所有有锁的卡扣、读取所有锁的RFID
- initKey() // 打开所有无钥匙的卡扣、关闭所有有钥匙的卡扣、读取所有钥匙的RFID
- return@repeatOnMain false
- } else {
- return@repeatOnMain true
- }
- }, REPEAT_FREQUENCY, true)
- }
- }
- /**
- * 初始化锁具——打开所有无锁的卡扣、读取RFID
- */
- private fun initLock() {
- LogUtil.i("initLock : $dockList")
- dockList.filter { it.type == DOCK_TYPE_LOCK || it.type == DOCK_TYPE_PORTABLE }
- .forEach { dockBean ->
- val hasLockIdxList =
- dockBean.getLockList().filter { it.isExist }.map { it.idx } as MutableList<Int>
- val noLockIdxList =
- dockBean.getLockList().filter { !it.isExist }.map { it.idx } as MutableList<Int>
- hasLockIdxList.forEach { idx ->
- readLockRfid(dockBean.addr, idx) { res ->
- if (res.size < 11) {
- LogUtil.e("Lock rfid error")
- return@readLockRfid
- }
- val rfid = res.copyOfRange(3, 11).toHexStrings(false).removeLeadingZeros()
- LogUtil.i("初始化锁具 RFID : $rfid")
- updateLockRfid(dockBean.addr, idx, rfid)
- NetApi.getLockInfo(rfid) {
- updateLockNewHardware(dockBean.addr, idx, it == null)
- }
- }
- }
- controlLockBuckle(false, dockBean.addr, hasLockIdxList)
- controlLockBuckle(true, dockBean.addr, noLockIdxList)
- }
- }
- /**
- * 初始化钥匙
- */
- private fun initKey() {
- LogUtil.i("initKey : $dockList")
- dockList.filter { it.type == DOCK_TYPE_KEY || it.type == DOCK_TYPE_PORTABLE }
- .forEach { dockBean ->
- dockBean.getKeyList().forEach { key ->
- if (key.isExist) {
- LogUtil.i("initKey : ${dockBean.addr} : ${key.isLeft}")
- readKeyRfid(dockBean.addr, if (key.isLeft) 0 else 1) { isLeft, res ->
- if (res.size < 11) {
- LogUtil.e("Key rfid error")
- return@readKeyRfid
- }
- val rfid =
- res.copyOfRange(3, 11).toHexStrings(false).removeLeadingZeros()
- LogUtil.i("初始化钥匙 RFID : $rfid")
- // 更新rfid
- updateKeyRfid(dockBean.addr, isLeft, rfid)
- // 蓝牙准备操作
- NetApi.getKeyInfo(rfid) {
- LogUtil.i("getKeyInfo : $rfid - ${it?.macAddress}")
- updateKeyNewHardware(dockBean.addr, isLeft, it == null)
- if (it != null && !it.macAddress.isNullOrEmpty()) {
- // 更新mac
- updateKeyMac(dockBean.addr, key.isLeft, it.macAddress)
- BusinessManager.registerConnectListener(
- it.macAddress,
- false
- ) { isDone, bleBean ->
- if (isDone && bleBean?.bleDevice != null) {
- Executor.delayOnMain(500) {
- BusinessManager.getCurrentStatus(
- 3, bleBean.bleDevice
- )
- }
- }
- }
- } else {
- ToastUtils.tip(R.string.get_key_info_fail)
- }
- }
- }
- controlKeyBuckle(false, key.isLeft, dockBean.addr)
- } else {
- controlKeyBuckle(true, key.isLeft, dockBean.addr)
- }
- }
- }
- }
- /**
- * 获取最新状态
- */
- fun updateStatus(byteArray: ByteArray): DockBean? {
- if (byteArray.isEmpty()) {
- return null
- }
- val dockB = dockList.find { it.addr == byteArray[0] }
- return dockB?.parseStatus(byteArray)
- }
- /**
- * 更新所有锁仓状态
- */
- fun updateAllBuckleStatus(done: () -> Unit) {
- val remaining = AtomicInteger(2)
- modBusManager?.sendToAll(MBFrame.READ_BUCKLE_STATUS) { res ->
- LogUtil.i("****************************************************************************")
- // 过滤非空的数据,重置slaveCount
- // 不再使用slaveCount,改用地址池
- lockBuckleStatus(res)
- // 每完成一个就把计数减一,减到 0 就触发 done()
- if (remaining.decrementAndGet() == 0) {
- done()
- }
- }
- modBusManager?.sendToAll(MBFrame.READ_LOCK_BUCKLE_EXTRA_STATUS) { res ->
- LogUtil.i("****************************************************************************")
- // 过滤非空的数据,重置slaveCount
- // 不再使用slaveCount,改用地址池
- lockBuckleExtraStatus(res)
- // 每完成一个就把计数减一,减到 0 就触发 done()
- if (remaining.decrementAndGet() == 0) {
- done()
- }
- }
- }
- /**
- * 更新开关状态
- */
- fun updateSwitchStatus(done: () -> Unit) {
- modBusManager?.mSlaveAddressList?.find { it == (0xA1).toByte() }?.let {
- modBusManager?.sendTo(it, MBFrame.READ_BUCKLE_STATUS) { res ->
- LogUtil.i("****************************************************************************")
- // 过滤非空的数据,重置slaveCount
- // 不再使用slaveCount,改用地址池
- switchStatus(res, done)
- }
- }
- }
- /**
- * 第9,10锁位卡扣状态
- */
- private fun lockBuckleExtraStatus(res: Any) {
- LogUtil.i("硬件状态:${(res as List<ByteArray>).map { it.toHexStrings() }}")
- if (res.isEmpty() || res.any { it.isEmpty() }) {
- var tipStr = CommonUtils.getStr(R.string.no_response_board_exists) + " : "
- val addressList = mutableListOf<String>()
- modBusManager?.mSlaveAddressList?.forEach { itDock ->
- if (res.none { it.isNotEmpty() && it[0] == itDock }) {
- addressList.add("0x${String.format("%02X", itDock)}")
- }
- }
- tipStr += addressList
- ToastUtils.tip(tipStr)
- }
- res.forEach { bytes ->
- val dockBean = updateExtraLockStatus(bytes) ?: return@forEach
- if (!CAN_RETURN) {
- return@forEach
- }
- when (dockBean.type) {
- DOCK_TYPE_LOCK -> {
- dockBean.getLockList().filter { it.idx > 7 }.forEach { lockBean ->
- updateLockStatus(
- dockBean.addr, lockBean.idx, lockBean.lockEnabled
- )
- }
- }
- }
- }
- }
- /**
- * 开关量更新
- */
- private fun switchStatus(res: Any, done: () -> Unit) {
- LogUtil.i("开关板:${(res as ByteArray).toHexStrings()}")
- if (res.isEmpty()) {
- var tipStr = CommonUtils.getStr(R.string.no_response_board_exists) + " : "
- val addressList = mutableListOf<String>()
- modBusManager?.mSlaveAddressList?.forEach { itDock ->
- if (res.isNotEmpty() && res == itDock) {
- addressList.add("0x${String.format("%02X", itDock)}")
- }
- }
- tipStr += addressList
- ToastUtils.tip(tipStr)
- }
- updateSwitchStatus(res, done)
- }
- /**
- * 第1-8锁位卡扣状态和钥匙
- */
- private fun lockBuckleStatus(res: Any) {
- LogUtil.i("硬件状态:${(res as List<ByteArray>).map { it.toHexStrings() }}")
- if (res.isEmpty() || res.any { it.isEmpty() }) {
- var tipStr = CommonUtils.getStr(R.string.no_response_board_exists) + " : "
- val addressList = mutableListOf<String>()
- modBusManager?.mSlaveAddressList?.forEach { itDock ->
- if (res.none { it.isNotEmpty() && it[0] == itDock }) {
- addressList.add("0x${String.format("%02X", itDock)}")
- }
- }
- tipStr += addressList
- ToastUtils.tip(tipStr)
- }
- res.forEach { bytes ->
- val dockBean = updateLockStatus(bytes) ?: return@forEach
- if (!CAN_RETURN) {
- return@forEach
- }
- when (dockBean.type) {
- DOCK_TYPE_KEY -> {
- dockBean.getKeyList().forEach { keyBean ->
- updateKeyLockStatus(
- dockBean.addr, keyBean.isLeft, keyBean.lockEnabled
- )
- //todo 更新锁仓状态
- }
- }
- DOCK_TYPE_LOCK -> {
- dockBean.getLockList().forEach { lockBean ->
- updateLockStatus(
- dockBean.addr, lockBean.idx, lockBean.lockEnabled
- )
- }
- }
- DOCK_TYPE_ELEC_LOCK_BOARD -> {
- // TODO 占位
- }
- DOCK_TYPE_PORTABLE -> {
- // TODO 便携式待完善
- dockBean.deviceList.forEach { deviceBean ->
- if (deviceBean.isExist) {
- when (deviceBean.type) {
- DEVICE_TYPE_KEY -> {
- updateKeyLockStatus(
- dockBean.addr, true, deviceBean.lockEnabled
- )
- }
- DEVICE_TYPE_LOCK -> {
- updateLockStatus(
- dockBean.addr, deviceBean.idx, deviceBean.lockEnabled
- )
- }
- DEVICE_TYPE_CARD -> {
- readPortalCaseCardRfid(dockBean.addr) { res ->
- if (res.size < 11) {
- LogUtil.e("Portal Case card rfid error")
- return@readPortalCaseCardRfid
- }
- val rfid = res.copyOfRange(3, 11).toHexStrings(false)
- .removeLeadingZeros()
- LogUtil.i("卡片RFID : $rfid")
- }
- }
- DEVICE_TYPE_FINGERPRINT -> {
- }
- }
- }
- }
- }
- }
- }
- }
- /**
- * 获取第1-8的锁仓数据和左右钥匙数据
- */
- private fun updateLockStatus(byteArray: ByteArray): DockBean? {
- if (byteArray.isEmpty()) {
- return null
- }
- val dockB = dockList.find { it.addr == byteArray[0] }
- return dockB?.parseLockStatus(byteArray)
- }
- /**
- * 更新开关状态
- */
- private fun updateSwitchStatus(byteArray: ByteArray, done: () -> Unit): DockBean? {
- if (byteArray.isEmpty()) {
- return null
- }
- val dockB = dockList.find { it.addr == byteArray[0] }
- return dockB?.parseSwitchStatus(byteArray, done)
- }
- /**
- * 获取额外的9,10锁仓数据
- */
- private fun updateExtraLockStatus(byteArray: ByteArray): DockBean? {
- if (byteArray.isEmpty()) {
- return null
- }
- val dockB = dockList.find { it.addr == byteArray[0] && it.type == DOCK_TYPE_LOCK }
- return dockB?.parseExtraLockStatus(byteArray)
- }
- /**
- * 读取设备类型
- */
- private fun readDeviceType(done: ((res: List<ByteArray>) -> Unit)? = null) {
- modBusManager?.sendToAll(MBFrame.READ_DEVICE_TYPE) { res ->
- done?.invoke(res)
- }
- }
- /**
- * 更新设备类型
- */
- private fun updateDeviceType(idx: Byte, type: Byte?) {
- val dock = dockList.find { it.addr == idx }
- dock?.let {
- it.type = type
- } ?: let {
- dockList.add(DockBean(idx, type, true, mutableListOf()))
- }
- }
- /**
- * 读取卡扣状态
- *
- * @param isLock true:读锁具底座 false:读钥匙底座
- * @param type 0:钥匙底座 1:锁具底座1-8 2:锁具底座9、10
- */
- fun readBuckleStatus(
- isLock: Boolean,
- slaveAddress: Byte?,
- doneSingle: ((type: Int, res: ByteArray) -> Unit)? = null
- ) {
- // TODO 电磁锁控制板可能不是,并且锁和钥匙的读取不一样
- slaveAddress?.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, slaveAddress: Byte?, lockIdx: Int, done: ((res: ByteArray) -> Unit)? = null
- ) {
- slaveAddress?.let {
- ModBusCMDHelper.generateLockBuckleCmd(isOpen, lockIdx)?.let { cmd ->
- modBusManager?.sendTo(it, cmd) { res ->
- done?.invoke(res)
- }
- }
- }
- }
- /**
- * 开/关锁具卡扣 多
- */
- fun controlLockBuckle(
- isOpen: Boolean,
- slaveAddress: Byte?,
- lockIdxList: MutableList<Int>,
- done: ((res: ByteArray) -> Unit)? = null
- ) {
- slaveAddress?.let {
- ModBusCMDHelper.generateLockBuckleCmd(isOpen, lockIdxList)?.let { cmdList ->
- cmdList.forEach { cmd ->
- modBusManager?.sendTo(it, cmd) { res ->
- done?.invoke(res)
- }
- }
- }
- }
- }
- /**
- * 读取钥匙RFID
- */
- fun readKeyRfid(
- slaveAddress: Byte?, idx: Int, done: ((isLeft: Boolean, res: ByteArray) -> Unit)? = null
- ) {
- slaveAddress?.let {
- ModBusCMDHelper.generateRfidCmd(idx)?.let { cmd ->
- modBusManager?.sendTo(it, cmd) {
- done?.invoke(idx == 0, it)
- }
- }
- }
- }
- /**
- * 读取锁具RFID
- */
- fun readLockRfid(slaveAddress: Byte?, lockIdx: Int, done: ((res: ByteArray) -> Unit)? = null) {
- slaveAddress?.let {
- ModBusCMDHelper.generateRfidCmd(lockIdx)?.let { cmd ->
- modBusManager?.sendTo(it, cmd) { res ->
- done?.invoke(res)
- }
- }
- }
- }
- /**
- * 读便携式底座卡RFID
- */
- fun readPortalCaseCardRfid(slaveAddress: Byte?, done: ((res: ByteArray) -> Unit)? = null) {
- slaveAddress?.let {
- ModBusCMDHelper.generateRfidCmd(8)?.let { cmd ->
- modBusManager?.sendTo(it, cmd) { res ->
- done?.invoke(res)
- }
- }
- }
- }
- /**
- * 更新钥匙RFID
- */
- fun updateKeyRfid(slaveAddress: Byte, isLeft: Boolean, rfid: String) {
- dockList.find { it.addr == slaveAddress }?.getKeyList()
- ?.find { it.isLeft == isLeft }?.rfid = rfid
- }
- /**
- * 更新钥匙锁仓状态
- */
- private fun updateKeyLockStatus(slaveAddress: Byte, isLeft: Boolean, lockEnabled: Boolean) {
- dockList.find { it.addr == slaveAddress }?.getKeyList()
- ?.find { it.isLeft == isLeft }?.lockEnabled = lockEnabled
- }
- /**
- * 更新钥匙MAC
- */
- fun updateKeyMac(slaveAddress: Byte, isLeft: Boolean, mac: String) {
- dockList.find { it.addr == slaveAddress }?.getKeyList()?.find { it.isLeft == isLeft }?.mac =
- mac
- }
- /**
- * 更新钥匙时候为新设备
- */
- fun updateKeyNewHardware(slaveAddress: Byte, isLeft: Boolean, newHardware: Boolean) {
- dockList.find { it.addr == slaveAddress }?.getKeyList()
- ?.find { it.isLeft == isLeft }?.newHardware = newHardware
- }
- /**
- * 更新锁具RFID
- */
- fun updateLockRfid(slaveAddress: Byte, lockIdx: Int, rfid: String) {
- dockList.find { it.addr == slaveAddress }?.getLockList()?.find { it.idx == lockIdx }?.rfid =
- rfid
- }
- /**
- * 更新锁是不是新设备,就是后台没有数据的
- */
- fun updateLockNewHardware(slaveAddress: Byte, lockIdx: Int, newHardware: Boolean) {
- dockList.find { it.addr == slaveAddress }?.getLockList()
- ?.find { it.idx == lockIdx }?.newHardware = newHardware
- }
- /**
- * 更新锁仓状态
- */
- fun updateLockStatus(slaveAddress: Byte, lockIdx: Int, lockEnabled: Boolean) {
- dockList.find { it.addr == slaveAddress }?.getLockList()
- ?.find { it.idx == lockIdx }?.lockEnabled = lockEnabled
- }
- /**
- * 控制钥匙卡扣
- */
- fun controlKeyBuckle(isOpen: Boolean, mac: String, done: ((res: ByteArray) -> Unit)? = null) {
- val dockBean = getDockByKeyMac(mac)
- dockBean ?: return
- val key = getKeyByMac(mac)
- key ?: return
- controlKeyBuckle(isOpen, key.isLeft, dockBean.addr, done)
- }
- /**
- * 开/关钥匙卡扣
- *
- * @param isOpen true:开操作 false:关操作
- * @param isLeft true:左卡扣 false:右卡扣
- */
- fun controlKeyBuckle(
- isOpen: Boolean,
- isLeft: Boolean,
- slaveAddress: Byte?,
- done: ((res: ByteArray) -> Unit)? = null
- ) {
- slaveAddress?.let {
- ModBusCMDHelper.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.filter { it.type == DOCK_TYPE_KEY || it.type == DOCK_TYPE_PORTABLE }
- .flatMap { it.getKeyList() }.find { it.rfid == rfid }
- }
- /**
- * 根据Mac找钥匙
- */
- fun getKeyByMac(mac: String): DockBean.KeyBean? {
- return dockList.filter { it.type == DOCK_TYPE_KEY || it.type == DOCK_TYPE_PORTABLE }
- .flatMap { it.getKeyList() }.find { it.mac == mac }
- }
- /**
- * 根据底座获取钥匙
- */
- fun getKeyByDock(dockAddr: Byte?, isLeft: Boolean): DockBean.KeyBean? {
- dockAddr ?: return null
- return dockList.find { it.addr == dockAddr }?.getKeyList()?.find { it.isLeft == isLeft }
- }
- /**
- * 钥匙是否存在
- */
- fun isKeyExist(dockAddr: Byte?, isLeft: Boolean): Boolean {
- dockAddr ?: return false
- return dockList.find { it.addr == dockAddr }?.getKeyList()
- ?.find { it.isLeft == isLeft && it.isExist } != null
- }
- /**
- * 获取钥匙锁仓的锁定状态
- */
- fun getKeyBuckleLockEnabled(dockAddr: Byte?, isLeft: Boolean): Boolean {
- dockAddr ?: return false
- return dockList.find { it.addr == dockAddr }?.getKeyList()
- ?.find { it.isLeft == isLeft }?.lockEnabled == true
- }
- /**
- * 获取挂锁锁仓的锁定状态
- */
- fun getLockBuckleLockEnabled(dockAddr: Byte?, lockIdx: Int): Boolean {
- dockAddr ?: return false
- return dockList.find { it.addr == dockAddr }?.getLockList()
- ?.find { it.idx == lockIdx }?.lockEnabled == true
- }
- /**
- * 获取挂锁是否存在
- */
- fun isLockExist(dockAddr: Byte?, lockIdx: Int): Boolean {
- dockAddr ?: return false
- return dockList.find { it.addr == dockAddr }?.getLockList()
- ?.find { it.idx == lockIdx && it.isExist } != null
- }
- /**
- * 获取钥匙状态
- *
- * @return 0:不存在 1:存在 2:有RFID 3:有MAC 4:连接上 5:待机模式 6: 待机模式无异常
- */
- fun getKeyStatus(dockAddr: Byte?, isLeft: Boolean): Int {
- dockAddr ?: return 0
- val key = dockList.find { it.addr == dockAddr }?.getKeyList()?.find { it.isLeft == isLeft }
- LogUtil.i("getKeyStatus key : $key")
- key ?: return 0
- var status = 0
- if (key.isExist) {
- status = 1
- } else {
- return status
- }
- if (key.rfid != null) {
- status = 2
- } else {
- return status
- }
- if (key.mac != null) {
- status = 3
- } else {
- return status
- }
- if (BleManager.getInstance()
- .isConnected(BusinessManager.getBleDeviceByMac(key.mac)?.bleDevice)
- ) {
- status = 4
- } else {
- return status
- }
- if (key.isReady) {
- status = 5
- } else {
- return status
- }
- if (key.rfid != null && BusinessManager.mExceptionKeyList.none { it == key.rfid }) {
- status = 6
- } else {
- return status
- }
- return status
- }
- /**
- * 更新钥匙的准备状态
- */
- fun updateKeyReadyStatus(mac: String, isReady: Boolean, from: Int) {
- LogUtil.i("updateKeyReadyStatus mac : $mac - $isReady - $from")
- dockList.forEach {
- if (it.type == DOCK_TYPE_KEY || it.type == DOCK_TYPE_PORTABLE) {
- if (it.getKeyList().any { it.mac == mac }) {
- it.getKeyList().find { it.mac == mac }?.isReady = isReady
- }
- }
- }
- }
- /**
- * 根据钥匙Mac获取底座
- */
- fun getDockByKeyMac(mac: String): DockBean? {
- return dockList.find {
- (it.type == DOCK_TYPE_KEY || it.type == DOCK_TYPE_PORTABLE) && it.getKeyList()
- .any { it.mac == mac }
- }
- }
- /**
- * 根据类型获取底座列表
- */
- fun getDockByType(type: Byte): List<DockBean> {
- return dockList.filter { it.type == type }
- }
- /**
- * 根据底座类型获取钥匙列表
- */
- fun getKeyByDockType(type: Byte): MutableList<DockBean.KeyBean>? {
- return dockList.find { it.type == type }?.let {
- it.getKeyList()
- }
- }
- /**
- * 全部锁扣的开关
- */
- fun controlAllLockBuckles(isOpen: Boolean) {
- dockList.filter { it.type == DOCK_TYPE_LOCK || it.type == DOCK_TYPE_PORTABLE }
- .forEach { dockBean ->
- val list =
- dockBean.getLockList().stream().map { it.idx }.collect(Collectors.toList())
- controlLockBuckle(isOpen, dockBean.addr, list) {
- LogUtil.i("${if (isOpen) "开启" else "关闭"}所有锁卡扣 : ${it.toHexStrings()}")
- }
- }
- }
- /**
- * 打印全部底座信息
- */
- fun printDockInfo() {
- LogUtil.i("当前底座列表 : $dockList")
- dockList.forEach { dockBean ->
- when (dockBean.type) {
- DOCK_TYPE_LOCK -> {
- dockBean.getLockList().forEach { lockBean ->
- LogUtil.i("${dockBean.addr}锁${lockBean.idx} : ${lockBean.rfid}")
- }
- }
- DOCK_TYPE_KEY -> {
- dockBean.getKeyList().forEach { keyBean ->
- LogUtil.i("${dockBean.addr}钥${keyBean.idx} : ${keyBean.rfid}")
- }
- }
- DOCK_TYPE_PORTABLE -> {
- dockBean.getLockList().forEach { lockBean ->
- LogUtil.i("${dockBean.addr}柜锁${lockBean.idx} : ${lockBean.rfid}")
- }
- dockBean.getKeyList().forEach { keyBean ->
- LogUtil.i("${dockBean.addr}柜钥${keyBean.idx} : ${keyBean.rfid}")
- }
- }
- }
- }
- }
- /**
- * 更新设备类型
- */
- fun updateDeviceType() {
- LogUtil.i("____________________________________")
- readDeviceType { res ->
- LogUtil.i("设备类型数量 : ${res.size}")
- LogUtil.i("设备类型 : ${res.map { it.toHexStrings() }}")
- res.forEach { bytes ->
- if (bytes.size < 5) return@forEach
- // 设备具体数据由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("设备(${bytes[0].toInt()})类型:$type")
- }
- LogUtil.i("____________________________________")
- }
- }
- /**
- * 随机获取一个钥匙(存在的、有RFID、有Mac、连接的、是待机模式的)
- *
- * @return 底座地址,钥匙
- */
- fun getOneKey(
- exceptionSlots: MutableList<CabinetSlotsRecord>,
- exceptionKeys: MutableList<String>
- ): Pair<Byte, DockBean.KeyBean?>? {
- val keyDockList =
- dockList.filter { it.type == DOCK_TYPE_KEY || it.type == DOCK_TYPE_PORTABLE }
- keyDockList.sortedBy { it.addr }
- keyDockList.forEach { it.deviceList.sortedBy { it.idx } }
- val keyList =
- keyDockList.map { it.deviceList }.flatten()
- .filterIsInstance<DockBean.KeyBean>()
- .filterIndexed { index, _ -> (index + 1) !in exceptionSlots.map { it.col?.toInt() } }
- .filter { it.rfid !in exceptionKeys && !it.rfid.isNullOrEmpty() && !it.mac.isNullOrEmpty() && it.isExist }
- .toMutableList()
- LogUtil.i("keyList : $keyList")
- if (keyList.isEmpty()) {
- ToastUtils.tip(R.string.no_available_key)
- return null
- }
- keyList.forEach {
- LogUtil.i(
- "keyStatus 满足条件的钥匙: ${it.isExist} - ${it.rfid} - ${it.mac} - ${it.isReady} - " + "${
- BusinessManager.getBleDeviceByMac(
- it.mac
- )?.bleDevice != null
- } - " + "${
- BleManager.getInstance()
- .isConnected(BusinessManager.getBleDeviceByMac(it.mac)?.bleDevice)
- } - " + "${!BusinessManager.mExceptionKeyList.contains(it.rfid)}"
- )
- }
- val key = keyList.filter {
- it.isExist && it.rfid != null && it.mac != null && it.isReady && BleManager.getInstance()
- .isConnected(BusinessManager.getBleDeviceByMac(it.mac)?.bleDevice) && !BusinessManager.mExceptionKeyList.contains(
- it.rfid
- )
- }.shuffled().firstOrNull()
- if (key == null) {
- LogUtil.e("getOneKey : no key match")
- return null
- }
- val address = keyDockList.find { it.getKeyList().any { it.rfid == key.rfid } }?.addr
- if (address == null) {
- LogUtil.e("getOneKey : no dock match")
- return null
- }
- return Pair(address, key)
- }
- /**
- * 根据数量获取锁具(基于锁柜和便携柜不存在接一起的情况)
- *
- * @param needLockCount 需要打开的锁具数量
- *
- * @return key: dock地址,value: 锁具RFID列表
- */
- fun getLocks(
- needLockCount: Int,
- exceptionSlots: MutableList<CabinetSlotsRecord>,
- exceptionLocks: MutableList<String>
- ): MutableMap<Byte, MutableList<DockBean.LockBean>> {
- val map = mutableMapOf<Byte, MutableList<DockBean.LockBean>>()
- if (needLockCount == 0) {
- return map
- }
- val lockDockList =
- dockList.filter { it.type == DOCK_TYPE_LOCK || it.type == DOCK_TYPE_PORTABLE }
- lockDockList.sortedBy { it.addr }
- var provideCount = 0
- for (lockDockIndex in lockDockList.indices) {
- if (provideCount >= needLockCount) break
- val validLocks =
- lockDockList[lockDockIndex].getLockList().filter { it.rfid !in exceptionLocks }
- .filter {
- it.isExist && it.idx !in exceptionSlots.filter { it.row?.toInt() == (lockDockIndex + 1) }
- .map { (it.col?.toInt() ?: 1) - 1 }
- }
- val toTake = (needLockCount - provideCount).coerceAtMost(validLocks.size)
- if (toTake > 0) {
- map[lockDockList[lockDockIndex].addr] = validLocks.take(toTake).toMutableList()
- provideCount += toTake
- }
- }
- return map
- }
- /**
- * 获取开关量数据
- */
- fun getSwitchData(): MutableList<DockBean.SwitchBean> {
- return dockList.filter { it.type == DOCK_TYPE_COLLECT }.sortedBy { it.addr }
- .flatMap { it.getSwitchList() }.mapIndexed { index, switchBean ->
- DockBean.SwitchBean(index, switchBean.switchBoardAddr, switchBean.enabled)
- }.toMutableList()
- }
- /**
- * 读取开关采集板数据
- */
- fun readSwitchStatus(
- slaveAddress: Byte?, addr: ByteArray, done: ((res: ByteArray) -> Unit)? = null
- ) {
- slaveAddress?.let {
- ModBusCMDHelper.generateSwitchBoardStatusCmd(addr)?.let { cmd ->
- modBusManager?.sendTo(it, cmd) { res ->
- done?.invoke(res)
- }
- }
- }
- }
- }
|