| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283 |
- package com.grkj.iscs_mars
- //todo 所有蓝牙包替换com.clj. -> com.clj.
- import android.bluetooth.BluetoothGattCharacteristic
- import android.content.Context
- import android.content.Intent
- import androidx.appcompat.app.AppCompatActivity
- import androidx.lifecycle.MutableLiveData
- import com.google.gson.Gson
- import com.grkj.iscs_mars.ble.BleBean
- import com.grkj.iscs_mars.ble.BleCmdManager
- import com.grkj.iscs_mars.ble.BleConnectionManager
- import com.grkj.iscs_mars.ble.BleConst
- import com.grkj.iscs_mars.ble.BleConst.STATUS_READY
- import com.grkj.iscs_mars.ble.BleConst.STATUS_WORK
- import com.grkj.iscs_mars.ble.BleReturnDispatcher
- import com.grkj.iscs_mars.ble.BleSendDispatcher
- import com.grkj.iscs_mars.ble.BleUtil
- import com.grkj.iscs_mars.ble.CustomBleWriteCallback
- import com.grkj.iscs_mars.enums.NoKeyReason
- import com.grkj.iscs_mars.extentions.removeLeadingZeros
- import com.grkj.iscs_mars.extentions.serialNo
- import com.grkj.iscs_mars.extentions.startsWith
- import com.grkj.iscs_mars.extentions.toHexStrings
- import com.grkj.iscs_mars.modbus.DockBean
- import com.grkj.iscs_mars.modbus.ModBusController
- import com.grkj.iscs_mars.modbus.ModBusController.dockList
- import com.grkj.iscs_mars.modbus.ModBusController.getOneKey
- import com.grkj.iscs_mars.model.Constants.USER_TYPE_LOCKER
- import com.grkj.iscs_mars.model.DeviceConst
- import com.grkj.iscs_mars.model.DeviceConst.DEVICE_TYPE_CARD
- import com.grkj.iscs_mars.model.DeviceConst.DEVICE_TYPE_FINGERPRINT
- import com.grkj.iscs_mars.model.DeviceConst.DEVICE_TYPE_KEY
- import com.grkj.iscs_mars.model.DeviceConst.DEVICE_TYPE_LOCK
- import com.grkj.iscs_mars.model.DeviceConst.DOCK_TYPE_ELEC_LOCK_BOARD
- import com.grkj.iscs_mars.model.DeviceConst.DOCK_TYPE_KEY
- import com.grkj.iscs_mars.model.DeviceConst.DOCK_TYPE_LOCK
- import com.grkj.iscs_mars.model.DeviceConst.DOCK_TYPE_PORTABLE
- import com.grkj.iscs_mars.model.DictAndSystemConstants
- import com.grkj.iscs_mars.model.ISCSDomainData
- import com.grkj.iscs_mars.model.bo.DeviceTakeUpdateBO
- import com.grkj.iscs_mars.model.bo.UpdateKeyReturnBO
- import com.grkj.iscs_mars.model.bo.WorkTicketGetBO
- import com.grkj.iscs_mars.model.bo.WorkTicketSendBO
- import com.grkj.iscs_mars.model.bo.WorkTicketSendBO.LockListBO
- import com.grkj.iscs_mars.model.eventmsg.CurrentModeMsg
- import com.grkj.iscs_mars.model.eventmsg.DeviceExceptionMsg
- import com.grkj.iscs_mars.model.eventmsg.DeviceTakeUpdateMsg
- import com.grkj.iscs_mars.model.eventmsg.LoadingMsg
- import com.grkj.iscs_mars.model.eventmsg.MsgEvent
- import com.grkj.iscs_mars.model.eventmsg.MsgEventConstants
- import com.grkj.iscs_mars.model.eventmsg.MsgEventConstants.MSG_EVENT_CURRENT_MODE
- import com.grkj.iscs_mars.model.eventmsg.MsgEventConstants.MSG_EVENT_DEVICE_EXCEPTION
- import com.grkj.iscs_mars.model.eventmsg.MsgEventConstants.MSG_EVENT_DEVICE_TAKE_UPDATE
- import com.grkj.iscs_mars.model.eventmsg.MsgEventConstants.MSG_EVENT_LOADING
- import com.grkj.iscs_mars.model.eventmsg.MsgEventConstants.MSG_EVENT_SWITCH_COLLECTION_UPDATE
- import com.grkj.iscs_mars.model.eventmsg.MsgEventConstants.MSG_EVENT_SWITCH_MODE
- import com.grkj.iscs_mars.model.eventmsg.MsgEventConstants.MSG_EVENT_UPDATE_TICKET_PROGRESS
- import com.grkj.iscs_mars.model.eventmsg.SwitchModeMsg
- import com.grkj.iscs_mars.model.eventmsg.UpdateTicketProgressMsg
- import com.grkj.iscs_mars.model.vo.dict.CommonDictRespVO
- import com.grkj.iscs_mars.model.vo.hardware.CabinetSlotsRespVo
- import com.grkj.iscs_mars.model.vo.hardware.SwitchListReqVO
- import com.grkj.iscs_mars.model.vo.key.KeyPageRespVO
- import com.grkj.iscs_mars.model.vo.lock.LockPageRespVO
- import com.grkj.iscs_mars.model.vo.lock.LockTakeUpdateReqVO
- import com.grkj.iscs_mars.model.vo.ticket.LockPointUpdateReqVO
- import com.grkj.iscs_mars.model.vo.ticket.TicketDetailRespVO
- import com.grkj.iscs_mars.service.CheckKeyInfoTask
- import com.grkj.iscs_mars.util.ActivityUtils
- import com.grkj.iscs_mars.util.CommonUtils
- import com.grkj.iscs_mars.util.Executor
- import com.grkj.iscs_mars.util.NetApi
- import com.grkj.iscs_mars.util.SPUtils
- import com.grkj.iscs_mars.util.ToastUtils
- import com.grkj.iscs_mars.util.log.LogUtil
- import com.grkj.iscs_mars.view.activity.LoginActivity
- import com.grkj.iscs_mars.view.base.BaseActivity
- import com.grkj.iscs_mars.view.dialog.TipDialog
- import com.huyuhui.fastble.data.BleDevice
- import com.huyuhui.fastble.exception.BleException
- import com.sik.cronjob.managers.CronJobScanner
- import com.sik.sikandroid.activity.ActivityTracker
- import com.sik.sikcore.SIKCore
- import com.sik.sikcore.date.TimeUtils
- import com.sik.sikcore.thread.ThreadUtils
- import kotlinx.coroutines.Dispatchers
- import kotlinx.coroutines.async
- import kotlinx.coroutines.suspendCancellableCoroutine
- import kotlinx.coroutines.withContext
- import kotlin.coroutines.resume
- /**
- * 业务层管理
- */
- object BusinessManager {
- // 消息总线
- val mEventBus = MutableLiveData<MsgEvent>()
- @JvmStatic
- @Volatile
- // 已连接的蓝牙钥匙集合
- var deviceList: MutableList<BleBean> = mutableListOf()
- // Modbus数据页面监听
- class DeviceListener(
- val key: Any, val callBack: (DockBean) -> Unit
- )
- private val listeners = ArrayList<DeviceListener>()
- private var initListener: (() -> Unit)? = null
- // 归还设备是否需要登录
- var NEED_AUTH = true
- // 归还设备是否需要登录及角色验证
- var CAN_RETURN = true
- get() {
- val loginUser = SPUtils.getLoginUser(MyApplication.instance!!.applicationContext!!)
- return (NEED_AUTH && loginUser != null) || !NEED_AUTH
- }
- // 设备待取列表(需要报给后台的列表,等实际取完再上报)
- @JvmStatic
- val mDeviceTakeList = mutableListOf<DeviceTakeUpdateBO>()
- // 是否是测试人员登录的
- var isTestMode = false
- // 有问题的钥匙的列表 - rfid
- var mExceptionKeyList = mutableListOf<String>()
- /**
- * 检查钥匙任务
- */
- var checkKeyInfoTask: CheckKeyInfoTask = CheckKeyInfoTask()
- /**
- * 初始化消息总线
- */
- fun initMsgEventBus() {
- mEventBus.observeForever {
- LogUtil.i("msgEvent : $it")
- when (it.code) {
- // loading消息
- MSG_EVENT_LOADING -> {
- Executor.runOnMain {
- val loadingMsg = it.data as LoadingMsg
- (ActivityUtils.currentActivity() as BaseActivity<*>).handleLoading(
- loadingMsg.isShow, loadingMsg.loadingText
- )
- }
- }
- // 设备取出
- MSG_EVENT_DEVICE_TAKE_UPDATE -> {
- handleDeviceTake(it.data as DeviceTakeUpdateMsg)
- }
- MsgEventConstants.MSG_EVENT_INIT_KEY_COMPLETE -> {
- val job = CronJobScanner.scanJobs(checkKeyInfoTask)
- MyApplication.cronJobManager.registerJobs(job)
- }
- // 钥匙当前模式
- MSG_EVENT_CURRENT_MODE -> {
- handleCurrentMode(it.data as CurrentModeMsg)
- }
- // 钥匙切换模式结果
- MSG_EVENT_SWITCH_MODE -> {
- when ((it.data as SwitchModeMsg).job) {
- // 工作模式
- 1 -> {
- if (it.data.res == 1) {
- // 只能在这里断开,不能全部断开
- BleSendDispatcher.scheduleDisconnect(it.data.bleBean.bleDevice.mac)
- // 打开钥匙卡扣
- val keyBean =
- ModBusController.getKeyByMac(it.data.bleBean.bleDevice.mac)
- if (keyBean == null) {
- sendEventMsg(
- MsgEvent(
- MSG_EVENT_LOADING,
- LoadingMsg(false, "未找到钥匙信息", false)
- )
- )
- ToastUtils.tip(R.string.key_not_exists)
- } else {
- sendLoadingEventMsg(CommonUtils.getStr(R.string.take_out_key_tip))
- val dock =
- ModBusController.getDockByKeyMac(it.data.bleBean.bleDevice.mac)
- keyBean.isReady = false
- ModBusController.controlKeyBuckle(
- true, keyBean.isLeft, dock?.addr
- )
- ModBusController.updateKeyReadyStatus(
- it.data.bleBean.bleDevice.mac, false, 1
- )
- ToastUtils.tip(R.string.take_out_key)
- ThreadUtils.runOnIO {
- checkMyTodoForHandleKey(it.data.bleBean.bleDevice.mac)
- }
- }
- } else {
- LogUtil.e("切换工作模式失败 : ${it.data.bleBean.bleDevice.mac}")
- Executor.delayOnMain(500) {
- switchWorkMode(it.data.bleBean.bleDevice, false)
- }
- }
- }
- // 待机模式
- 2 -> {
- if (it.data.res == 1) {
- ModBusController.updateKeyReadyStatus(
- it.data.bleBean.bleDevice.mac, true, 2
- )
- // 延时再次获取当前状态,触发handleCurrentMode里工作票下发状态检查
- Executor.delayOnMain(500) {
- getCurrentStatus(1, it.data.bleBean.bleDevice)
- }
- } else {
- LogUtil.e("切换待机模式失败 : ${it.data.bleBean.bleDevice.mac}")
- Executor.delayOnMain(500) {
- switchReadyMode(it.data.bleBean.bleDevice)
- }
- }
- }
- }
- }
- MSG_EVENT_SWITCH_COLLECTION_UPDATE -> {
- ThreadUtils.runOnIO {
- val switchListReqVOS = ModBusController.getSwitchData().map {
- SwitchListReqVO(
- it.idx.toString(),
- if (it.enabled) "1" else "0",
- TimeUtils.nowString(TimeUtils.DEFAULT_DATE_HOUR_MIN_SEC_FORMAT)
- )
- }
- NetApi.updateSwitchList(switchListReqVOS) {
- LogUtil.i("开关更新完成")
- }
- }
- }
- }
- }
- }
- /**
- * 检查我的待办
- */
- suspend fun checkMyTodoForHandleKey(mac: String? = null, delayMillis: Long = 60_0000): Boolean {
- if (!CAN_RETURN) {
- return false
- }
- val result = suspendCancellableCoroutine<Boolean> { cont ->
- NetApi.getMySelfState {
- if (it) {
- LogUtil.i("蓝牙连接-存在上锁解锁待办")
- if (BleSendDispatcher.canConnect()) {
- LogUtil.i("蓝牙连接-发送队列可以连接")
- mac?.let {
- connectExistsKey(listOf(it))
- }
- }
- } else {
- LogUtil.i("蓝牙连接-没有待办数据,延迟断开所有发送连接")
- BleSendDispatcher.disconnectAll(delayMillis)
- }
- if (cont.isActive) {
- cont.resume(it)
- }
- }
- }
- return result
- }
- /**
- * 连接一把存在的可连接的钥匙
- */
- fun connectExistsKey(exceptKeyMac: List<String> = listOf()) {
- ThreadUtils.runOnIO {
- // —— 串行请求1 & 2 ——
- val slotsPage = getSlotsPage()
- // —— 并行加载字典(或按需串行也行) ——
- val slotStatus =
- async { fetchDict<CommonDictRespVO>(DictAndSystemConstants.KEY_SLOT_STATUS) }
- val keyStatus =
- async { fetchDict<CommonDictRespVO>(DictAndSystemConstants.KEY_KEY_STATUS) }
- val slotType =
- async { fetchDict<CommonDictRespVO>(DictAndSystemConstants.KEY_SLOT_TYPE) }
- // 等待字典加载完成
- val slotStatusList = slotStatus.await()
- val keyStatusList = keyStatus.await()
- val slotTypeList = slotType.await()
- withContext(Dispatchers.Default) {
- val keyPage = withContext(Dispatchers.IO) { getKeyPage() }
- getOneKey(
- slotsPage?.records?.filter {
- it.slotType == slotTypeList.find { d -> d.dictLabel == "钥匙" }?.dictValue && it.status == slotStatusList.find { d -> d.dictLabel == "异常" }?.dictValue
- }?.toMutableList() ?: mutableListOf(),
- (keyPage?.records?.filter { it.exStatus == keyStatusList.find { d -> d.dictLabel == "异常" }?.dictValue }
- ?.map { it.keyNfc ?: "" }?.toMutableList() ?: mutableListOf()),
- exceptKeyMac
- )
- }
- }
- }
- /****************************************** ModBus ******************************************/
- /**
- * 链接底座
- */
- fun connectDock(isNeedInit: Boolean = false) {
- ModBusController.interruptReadTrashBinStatus(false)
- ModBusController.start(MyApplication.instance!!.applicationContext)
- ModBusController.unregisterListener(MyApplication.instance!!.applicationContext)
- if (isNeedInit) {
- ModBusController.initDevicesStatus()
- }
- }
- /**
- * 断开底座链接
- */
- fun disconnectDock() {
- ModBusController.stop()
- }
- /**
- * 注册状态监听
- */
- fun registerStatusListener(key: Any, listener: (DockBean) -> Unit) {
- listeners.add(DeviceListener(key, listener))
- }
- /**
- * 注册初始化监听
- */
- fun registerInitListener(listener: () -> Unit) {
- this.initListener = listener
- }
- /**
- * 取消注册初始化监听
- */
- fun unRegisterInitListener() {
- this.initListener = null
- }
- /**
- * 取消注册状态监听
- */
- fun unregisterListener(key: Any) {
- val it = listeners.iterator()
- while (it.hasNext()) {
- if (it.next().key == key) {
- it.remove()
- }
- }
- }
- /**
- * 总的监听,做预处理,其余的所有监听均使用本监听处理后的数据,只允许调用一次
- */
- fun registerMainListener() {
- ModBusController.registerStatusListener(this) { res ->
- deviceStatusHandle(res)
- }
- }
- /**
- * 硬件状态
- * 1、检测到有钥匙
- * 2、上锁
- * 3、开启充电
- * 4、蓝牙连接
- * 5、蓝牙数据通讯
- */
- private fun deviceStatusHandle(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>()
- ModBusController.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.forEachIndexed { index, bytes ->
- val dockBean = ModBusController.updateStatus(bytes) ?: return@forEachIndexed
- ModBusController.isInitReady = true
- when (dockBean.type) {
- DOCK_TYPE_KEY -> {
- if (!CAN_RETURN) {
- return@forEachIndexed
- }
- dockBean.getKeyList().forEach { keyBean ->
- deviceKeyHandler(dockBean, keyBean)
- }
- }
- DOCK_TYPE_LOCK -> {
- if (!CAN_RETURN) {
- return@forEachIndexed
- }
- dockBean.getLockList().forEach { lockBean ->
- deviceLockHandler(dockBean, lockBean)
- }
- }
- DOCK_TYPE_ELEC_LOCK_BOARD -> {
- // TODO 占位
- }
- DOCK_TYPE_PORTABLE -> {
- // TODO 便携式待完善
- dockBean.deviceList.forEach { deviceBean ->
- if (deviceBean.isExist) {
- when (deviceBean.type) {
- DEVICE_TYPE_KEY -> {
- if (!CAN_RETURN) {
- return@forEachIndexed
- }
- deviceKeyHandler(dockBean, deviceBean as DockBean.KeyBean)
- }
- DEVICE_TYPE_LOCK -> {
- if (!CAN_RETURN) {
- return@forEachIndexed
- }
- deviceLockHandler(dockBean, deviceBean as DockBean.LockBean)
- }
- DEVICE_TYPE_CARD -> {
- ModBusController.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 -> {
- }
- }
- }
- }
- }
- DeviceConst.DOCK_TYPE_COLLECT -> {
- ModBusController.switchStatus(bytes) {}
- }
- }
- Executor.delayOnMain(200) {
- if (!ISCSDomainData.isDeviceRegistration) {
- listeners.forEach { it.callBack(dockBean) }
- }
- }
- }
- Executor.delayOnMain(200) {
- if (ISCSDomainData.isDeviceRegistration) {
- initListener?.invoke()
- }
- }
- }
- /**
- * 挂锁处理
- */
- private fun deviceLockHandler(
- dockBean: DockBean, lockBean: DockBean.LockBean
- ) {
- if (lockBean.isExist) {
- ModBusController.readLockRfid(dockBean.addr, lockBean.idx) { res ->
- if (res.size < 11) {
- LogUtil.e("Lock rfid error")
- return@readLockRfid
- }
- val rfid = res.copyOfRange(3, 11).toHexStrings(false).removeLeadingZeros()
- ModBusController.updateLockRfid(
- dockBean.addr, lockBean.idx, rfid
- )
- ThreadUtils.runOnIO {
- val lockStatusReq =
- async { fetchDict<CommonDictRespVO>(DictAndSystemConstants.KEY_PAD_LOCK_STATUS) }
- val slotStatus =
- async { fetchDict<CommonDictRespVO>(DictAndSystemConstants.KEY_SLOT_STATUS) }
- val slotType =
- async { fetchDict<CommonDictRespVO>(DictAndSystemConstants.KEY_SLOT_TYPE) }
- val slotsPageReq = async { getSlotsPage() }
- var lockStatus = lockStatusReq.await()
- val slotsPage = slotsPageReq.await()
- val slotStatusList = slotStatus.await()
- val slotTypeList = slotType.await()
- NetApi.getIsLockPage { lockData ->
- //锁rfid未异常正常请求锁数据,关锁
- if (rfid in (lockData?.records?.filter { it.exStatus == lockStatus.find { it.dictLabel == "异常" }?.dictValue }
- ?.map { it.lockNfc }?.toMutableList() ?: mutableListOf())) {
- ToastUtils.tip(
- MyApplication.instance?.applicationContext!!.getString(
- R.string.lock_exception_tag
- )
- )
- } else if (slotsPage?.records?.filter {
- it.slotType == slotTypeList.find { d -> d.dictLabel == "锁" }?.dictValue && it.status == slotStatusList.find { d -> d.dictLabel == "异常" }?.dictValue
- }
- ?.find { it.row?.toInt() == dockBean.row && (lockBean.idx + 1) == it.col?.toInt() } != null) {
- ToastUtils.tip(
- MyApplication.instance?.applicationContext!!.getString(
- R.string.slot_exception_tag
- )
- )
- } else {
- NetApi.getLockInfo(rfid) {
- if (it != null) {
- NetApi.getLockStateByNfc(rfid) {
- if (it != 1) {
- ModBusController.controlLockBuckle(
- false, dockBean.addr, lockBean.idx
- ) { itRst ->
- if (itRst.isNotEmpty()) {
- // 上报锁具信息
- NetApi.updateLockReturn(
- rfid, MyApplication.instance!!.serialNo()
- ) {}
- }
- }
- } else {
- ToastUtils.tip(CommonUtils.getStr(R.string.ticket_not_finish_can_not_return_lock))
- }
- }
- }
- }
- }
- }
- }
- }
- } else {
- LogUtil.i("挂锁取出-:${lockBean.rfid}")
- sendEventMsg(
- MsgEvent(
- MSG_EVENT_DEVICE_TAKE_UPDATE,
- DeviceTakeUpdateMsg(DEVICE_TYPE_LOCK, lockBean.rfid)
- )
- )
- }
- }
- private fun deviceKeyHandler(dockBean: DockBean, keyBean: DockBean.KeyBean) {
- if (keyBean.isExist) {
- // 放回钥匙,读取rfid
- ModBusController.readKeyRfid(
- dockBean.addr, if (keyBean.isLeft) 0 else 1
- ) { isLeft, res ->
- if (!ISCSDomainData.isDeviceRegistration) {
- ModBusController.controlKeyCharge(
- true, keyBean.isLeft, dockBean.addr
- )
- }
- if (res.size < 11) {
- LogUtil.e("Key rfid error")
- return@readKeyRfid
- }
- val rfid = res.copyOfRange(3, 11).toHexStrings(false).removeLeadingZeros()
- ThreadUtils.runOnIO {
- val slotStatus =
- async { fetchDict<CommonDictRespVO>(DictAndSystemConstants.KEY_SLOT_STATUS) }
- val slotType =
- async { fetchDict<CommonDictRespVO>(DictAndSystemConstants.KEY_SLOT_TYPE) }
- val slotsPageReq = async { getSlotsPage() }
- val keyStatusReq =
- async { fetchDict<CommonDictRespVO>(DictAndSystemConstants.KEY_KEY_STATUS) }
- val keyPageReq = async { getKeyPage() }
- var keyStatus = keyStatusReq.await()
- var keyData = keyPageReq.await()
- val slotsPage = slotsPageReq.await()
- val slotStatusList = slotStatus.await()
- val slotTypeList = slotType.await()
- //锁钥匙未异常正常请求锁数据,关锁
- if (rfid in (keyData?.records?.filter { it.exStatus == keyStatus.find { it.dictLabel == "异常" }?.dictValue }
- ?.map { it.keyNfc }?.toMutableList() ?: mutableListOf())) {
- ToastUtils.tip(
- MyApplication.instance?.applicationContext!!.getString(
- R.string.key_exception_tag
- )
- )
- } else if (slotsPage?.records?.filter {
- it.slotType == slotTypeList.find { d -> d.dictLabel == "钥匙" }?.dictValue && it.status == slotStatusList.find { d -> d.dictLabel == "异常" }?.dictValue
- }
- ?.find { it.row?.toInt() == dockBean.row && it.col?.toInt() == (dockBean.col + (if (keyBean.isLeft) 0 else 1) * 2) } != null) {
- ToastUtils.tip(
- MyApplication.instance?.applicationContext!!.getString(
- R.string.slot_exception_tag
- )
- )
- } else {
- ModBusController.updateKeyRfid(
- dockBean.addr, keyBean.isLeft, rfid
- )
- // 放回钥匙,上锁
- ModBusController.controlKeyBuckle(
- false, keyBean.isLeft, dockBean.addr
- ) {
- NetApi.getKeyInfo(rfid) {
- ModBusController.updateKeyNewHardware(
- dockBean.addr, true, it == null
- )
- if (it != null && !it.macAddress.isNullOrEmpty()) {
- ModBusController.updateKeyMac(
- dockBean.addr, keyBean.isLeft, it.macAddress
- )
- ModBusController.updateKeyReadyStatus(
- it.macAddress, false, 5
- )
- } else {
- LogUtil.e("Get key info fail : $rfid")
- if (!ISCSDomainData.isDeviceRegistration) {
- ToastUtils.tip(R.string.get_key_info_fail)
- }
- ModBusController.controlKeyBuckle(
- true, keyBean.isLeft, dockBean.addr
- )
- }
- }
- }
- }
- }
- }
- } else if (!keyBean.isCharging) {//增加充电判断,防止无线充电干扰锁仓状态导致判断为取出
- // 移出待连监听集合,防止connectKey循环失败
- keyBean.mac?.let {
- unregisterConnectListener(it)
- }
- sendEventMsg(
- MsgEvent(
- MSG_EVENT_DEVICE_TAKE_UPDATE, DeviceTakeUpdateMsg(DEVICE_TYPE_KEY, keyBean.rfid)
- )
- )
- }
- }
- /**
- * 更新所有锁仓状态
- */
- fun updateAllBuckleStatus(done: () -> Unit) {
- ModBusController.updateAllBuckleStatus(done)
- }
- /**
- * 更新开关状态
- */
- fun updateSwitchStatus(done: () -> Unit) {
- ModBusController.updateSwitchStatus(done)
- }
- /**
- * 钥匙归还提示确认弹窗,当前策略:作业票未完成是否强制上传数据
- */
- private fun showKeyReturnUploadDataForceDialog(onConfirm: () -> Unit, onCancel: () -> Unit) {
- val ctx = ActivityUtils.currentActivity() as BaseActivity<*>
- val dlg = TipDialog(ctx)
- dlg.setTip(ctx.getString(R.string.key_return_force_tip))
- dlg.setType(TipDialog.TYPE_ALL)
- // 加个选择判断,如果是直接取消弹框而不是点击“确定”,当成确定
- var state = 0
- dlg.setConfirmListener {
- state = 1
- onConfirm.invoke()
- }
- dlg.setOnCancelListener {
- state = 2
- onCancel.invoke()
- }
- dlg.setOnDismissListener {
- if (state == 0) {
- onCancel.invoke()
- }
- }
- dlg.show()
- }
- /**
- * 钥匙归还提示确认弹框,当前策略:作业票未完成禁止归还钥匙
- */
- private fun showKeyReturnDialog(onConfirm: () -> Unit) {
- val ctx = ActivityUtils.currentActivity() as BaseActivity<*>
- val dlg = TipDialog(ctx)
- dlg.setTip(ctx.getString(R.string.key_return_tip))
- dlg.setType(TipDialog.TYPE_CONFIRM)
- // 加个选择判断,如果是直接取消弹框而不是点击“确定”,当成确定
- var state = 0
- dlg.setConfirmListener {
- state = 1
- onConfirm.invoke()
- }
- dlg.setOnDismissListener {
- if (state == 0) {
- onConfirm.invoke()
- }
- }
- dlg.show()
- }
- fun readLockBuckleStatus() {
- // TODO slaveIdx暂时写死,调试用
- ModBusController.readBuckleStatus(true, 0) { type, res ->
- LogUtil.i("单slave卡扣状态 : $type - ${res.toHexStrings()}")
- when (type) {
- 0 -> {
- val isLeftLock = (res[4].toInt() shr 0) and 0x1 == 1
- val isRightLock = (res[4].toInt() shr 4) and 0x1 == 1
- LogUtil.i("锁具底座卡扣状态 : $isLeftLock - $isRightLock")
- }
- 1 -> {
- val tempList = mutableListOf<Boolean>()
- for (i in 0..7) {
- tempList.add((res[4].toInt() shr i) and 0x1 == 1)
- }
- LogUtil.i("锁具底座卡扣1-8状态 : $tempList")
- }
- 2 -> {
- val lock9Status = (res[4].toInt() shr 0) and 0x1 == 1
- val lock10Status = (res[4].toInt() shr 1) and 0x1 == 1
- LogUtil.i("锁具底座卡扣9、10状态 : $lock9Status - $lock10Status")
- }
- }
- }
- }
- fun readKeyBuckleStatus() {
- // TODO slaveIdx暂时写死,调试用
- ModBusController.readBuckleStatus(false, 1) { type, res ->
- LogUtil.i("单slave卡扣状态 : $type - ${res.toHexStrings()}")
- // TODO 待验证
- when (type) {
- 0 -> {
- val isLeftLock = (res[4].toInt() shr 0) and 0x1 == 1
- val isRightLock = (res[4].toInt() shr 4) and 0x1 == 1
- LogUtil.i("钥匙底座卡扣状态 : $isLeftLock - $isRightLock")
- }
- 1 -> {
- val tempList = mutableListOf<Boolean>()
- for (i in 0..7) {
- tempList.add((res[4].toInt() shr i) and 0x1 == 1)
- }
- LogUtil.i("锁具底座卡扣1-8状态 : $tempList")
- }
- 2 -> {
- val lock9Status = (res[4].toInt() shr 0) and 0x1 == 1
- val lock10Status = (res[4].toInt() shr 1) and 0x1 == 1
- LogUtil.i("锁具底座卡扣9、10状态 : $lock9Status - $lock10Status")
- }
- }
- }
- }
- // 1. 把 NetApi.get…Page 包成 suspend 函数
- private suspend fun getSlotsPage(): CabinetSlotsRespVo? = suspendCancellableCoroutine { cont ->
- NetApi.getIsLockCabinetSlotsPage { slots ->
- cont.resume(slots)
- }
- }
- private suspend fun getLocksPage(): LockPageRespVO? = suspendCancellableCoroutine { cont ->
- NetApi.getIsLockPage { locks ->
- cont.resume(locks)
- }
- }
- private suspend fun getKeyPage(): KeyPageRespVO? = suspendCancellableCoroutine { cont ->
- NetApi.getIsKeyPage { keys ->
- cont.resume(keys)
- cont.cancel()
- }
- }
- // 2. 把原本同步的字典查询留在 IO 线程
- private suspend fun <T> fetchDict(key: String): List<T> = withContext(Dispatchers.IO) {
- @Suppress("UNCHECKED_CAST") NetApi.getDictData(key) as List<T>
- }
- // 3. 重写 checkEquipCount
- fun checkEquipCount(
- needLockCount: Int,
- isNeedKey: Boolean,
- callBack: (Pair<Byte, DockBean.KeyBean?>?, MutableMap<Byte, MutableList<DockBean.LockBean>>) -> Unit
- ) {
- // 你可以改成接收 CoroutineScope 或者直接在全局 Scope 启动
- ThreadUtils.runOnMain {
- sendLoadingEventMsg(MyApplication.instance?.applicationContext!!.getString(R.string.check_key_and_lock))
- try {
- // —— 串行请求1 & 2 ——
- val slotsPage = getSlotsPage()
- val locksPage = getLocksPage()
- // —— 并行加载字典(或按需串行也行) ——
- val lockStatus =
- async { fetchDict<CommonDictRespVO>(DictAndSystemConstants.KEY_PAD_LOCK_STATUS) }
- val slotStatus =
- async { fetchDict<CommonDictRespVO>(DictAndSystemConstants.KEY_SLOT_STATUS) }
- val slotType =
- async { fetchDict<CommonDictRespVO>(DictAndSystemConstants.KEY_SLOT_TYPE) }
- val keyStatus =
- async { fetchDict<CommonDictRespVO>(DictAndSystemConstants.KEY_KEY_STATUS) }
- // 等待字典加载完成
- val lockStatusList = lockStatus.await()
- val slotStatusList = slotStatus.await()
- val slotTypeList = slotType.await()
- val keyStatusList = keyStatus.await()
- // —— 在 Default 线程做计算密集操作 ——
- val lockMap = withContext(Dispatchers.Default) {
- ModBusController.getLocks(
- needLockCount,
- slotsPage?.records?.filter {
- it.slotType == slotTypeList.find { d -> d.dictLabel == "锁" }?.dictValue && it.status == slotStatusList.find { d -> d.dictLabel == "异常" }?.dictValue
- }?.toMutableList() ?: mutableListOf(),
- locksPage?.records?.filter { it.exStatus == lockStatusList.find { d -> d.dictLabel == "异常" }?.dictValue }
- ?.map { it.lockNfc ?: "" }?.toMutableList() ?: mutableListOf()
- )
- }
- // —— 如果需钥匙,再请求并计算 ——
- var keyPair: Pair<Byte, DockBean.KeyBean?>? = null
- if (isNeedKey) {
- val keyPage = withContext(Dispatchers.IO) { getKeyPage() }
- keyPair = withContext(Dispatchers.Default) {
- getOneKey(
- slotsPage?.records?.filter {
- it.slotType == slotTypeList.find { d -> d.dictLabel == "钥匙" }?.dictValue && it.status == slotStatusList.find { d -> d.dictLabel == "异常" }?.dictValue
- }?.toMutableList() ?: mutableListOf(),
- keyPage?.records?.filter { it.exStatus == keyStatusList.find { d -> d.dictLabel == "异常" }?.dictValue }
- ?.map { it.keyNfc ?: "" }?.toMutableList() ?: mutableListOf()
- )
- }
- }
- // —— 全部计算完毕,在主线程一次性回调 ——
- callBack(keyPair, lockMap)
- } catch (e: Exception) {
- // 根据需求处理异常,或把异常信息也通过 callback 返回
- sendLoadingEventMsg(null, false)
- e.printStackTrace()
- ToastUtils.tip("检查设备异常:${e.message}")
- }
- }
- }
- /****************************************** 蓝牙 ******************************************/
- /******************************************蓝牙通用准备******************************************/
- /**
- * 注册连接监听
- */
- fun registerConnectListener(
- mac: String, connectNow: Boolean = false, isSend: Boolean = true, callBack: ((
- Boolean, BleBean?
- ) -> Unit)? = null
- ) {
- BleConnectionManager.registerConnectListener(mac, connectNow, isSend, callBack)
- }
- /**
- * 连接监听反注册
- */
- fun unregisterConnectListener(mac: String, bleBean: BleBean? = null) {
- BleConnectionManager.unregisterConnectListener(mac, bleBean)
- }
- /******************************************蓝牙通用准备结束******************************************/
- fun getBleDeviceByMac(mac: String?): BleBean? {
- return deviceList.find { it.bleDevice.mac == mac }
- }
- fun getBleBeanByRfid(nfc: String?): BleBean? {
- nfc ?: return null
- ModBusController.getKeyByRfid(nfc)?.mac?.let { itMac ->
- return getBleDeviceByMac(itMac)
- }
- return null
- }
- /**
- * 下发工作票
- */
- private fun sendTicketBusiness(
- isLock: Boolean,
- mac: String,
- ticketDetail: TicketDetailRespVO,
- lockList: MutableList<String?>?,
- activity: AppCompatActivity,
- isNeedLoading: Boolean = false,
- ) {
- if (BleSendDispatcher.isConnected(mac)) {
- val bleBean = getBleDeviceByMac(mac)
- if (bleBean == null) {
- LogUtil.e("sendTicketBusiness fail : $mac, bleBean is null")
- return
- }
- // 单bleBean json赋值
- bleBean.retryCount = 0
- bleBean.ticketSend = generateTicketSendJson(isLock, ticketDetail, lockList)
- bleBean.ticketSend?.let { itJson ->
- sendTicketWithRetry(itJson, bleBean.bleDevice, isNeedLoading)
- }
- } else {
- ThreadUtils.runOnIODelayed(1000) {
- sendTicketBusiness(isLock, mac, ticketDetail, lockList, activity, isNeedLoading)
- }
- }
- }
- /**
- * 带重试的下发工作票,重试次数3,间隔500ms
- */
- private fun sendTicketWithRetry(
- json: String,
- bleDevice: BleDevice,
- isNeedLoading: Boolean = false,
- maxRetries: Int = 3,
- delayMillis: Long = 500
- ) {
- var retryCount = 0
- fun attemptSend() {
- sendTicket(json, bleDevice, isNeedLoading) { sendRst ->
- if (!sendRst && retryCount < maxRetries) {
- retryCount++
- // 等待一段时间后再次尝试
- Executor.delayOnMain(delayMillis) {
- LogUtil.i("Retry attempt, mac : ${bleDevice.mac}, retryCount : $retryCount")
- attemptSend()
- }
- }
- }
- }
- attemptSend()
- }
- /**
- * 读取工作票完成情况
- */
- private fun getTicketStatusBusiness(
- mac: String, isNeedLoading: Boolean = false
- ) {
- LogUtil.i("检查钥匙连接情况")
- if (BleReturnDispatcher.isConnected(mac)) {
- getBleDeviceByMac(mac)?.bleDevice?.let {
- LogUtil.i("开始读取作业票")
- BleReturnDispatcher.busy(mac)
- getTicketStatusWithRetry(
- it,
- isNeedLoading
- )
- }
- } else {
- //如果连接在待发列表则断开连接,重新使用归还队列连接之后检查
- if (BleSendDispatcher.isConnected(mac)) {
- BleSendDispatcher.scheduleDisconnect(mac)
- BleReturnDispatcher.submit(mac) {
- getTicketStatusBusiness(mac, isNeedLoading)
- }
- }
- if (isNeedLoading) sendEventMsg(
- MsgEvent(
- MSG_EVENT_LOADING, LoadingMsg(false, null, false)
- )
- )
- }
- }
- private fun getTicketStatusWithRetry(
- bleDevice: BleDevice,
- isNeedLoading: Boolean = false,
- maxRetries: Int = 3,
- delayMillis: Long = 500
- ) {
- var retryCount = 0
- fun attemptSend() {
- getTicketStatus(bleDevice, isNeedLoading) { sendRst ->
- if (!sendRst && retryCount < maxRetries) {
- retryCount++
- // 等待一段时间后再次尝试
- Executor.delayOnMain(delayMillis) {
- LogUtil.i("Retry attempt, mac : ${bleDevice.mac}, retryCount : $retryCount")
- attemptSend()
- }
- }
- }
- }
- attemptSend()
- }
- private fun sendTicket(
- jsonStr: String,
- bleDevice: BleDevice,
- isNeedLoading: Boolean = false,
- processCallback: ((Boolean) -> Unit)? = null
- ) {
- if (isNeedLoading) sendEventMsg(
- MsgEvent(
- MSG_EVENT_LOADING,
- LoadingMsg(true, CommonUtils.getStr(R.string.start_to_send_ticket), null)
- )
- )
- BleCmdManager.sendWorkTicket(
- jsonStr, bleDevice = bleDevice, callback = object : CustomBleWriteCallback() {
- override fun onWriteSuccess(
- bleDevice: BleDevice,
- characteristic: BluetoothGattCharacteristic,
- current: Int,
- total: Int,
- justWrite: ByteArray,
- data: ByteArray
- ) {
- LogUtil.i("sendTicket success")
- if (isNeedLoading) sendEventMsg(
- MsgEvent(
- MSG_EVENT_LOADING,
- LoadingMsg(true, CommonUtils.getStr(R.string.sending_ticket), null)
- )
- )
- }
- override fun onWriteFailure(
- bleDevice: BleDevice,
- characteristic: BluetoothGattCharacteristic?,
- exception: BleException,
- current: Int,
- total: Int,
- justWrite: ByteArray?,
- data: ByteArray?,
- isTotalFail: Boolean
- ) {
- LogUtil.e("sendTicket fail : ${bleDevice.mac}")
- if (isNeedLoading) sendEventMsg(
- MsgEvent(
- MSG_EVENT_LOADING,
- LoadingMsg(false, CommonUtils.getStr(R.string.send_ticket_fail), null)
- )
- )
- processCallback?.invoke(false)
- }
- })
- }
- /**
- * 生成下发工作票Json
- *
- * @param vo 工作票详情
- */
- private fun generateTicketSendJson(
- isLock: Boolean, vo: TicketDetailRespVO, lockList: MutableList<String?>?
- ): String {
- LogUtil.i("generateTicketSendJson : $lockList")
- val bo = WorkTicketSendBO(
- cardNo = SPUtils.getLoginUser(MyApplication.instance!!.applicationContext)?.userCardList?.get(
- 0
- ),
- )
- CommonUtils.getDiffHours(vo.ticketEndTime)?.let {
- bo.effectiveTime = it
- }
- // 有配置则用配置,没用则填充默认密码
- bo.password =
- SPUtils.getLoginUser(MyApplication.instance!!.applicationContext)?.keyCode ?: "123456"
- val dataBO = WorkTicketSendBO.DataBO(
- taskCode = vo.ticketId.toString(), codeId = 1
- )
- val taskList = ArrayList<WorkTicketSendBO.DataBO.DataListBO>()
- vo.ticketPointsVOList?.filter { it.pointStatus == if (isLock) "0" else "1" }
- ?.let { itList ->
- itList.forEach { pointVO ->
- if (vo.noUnlockTicketPointsVOSet?.any { it.pointId == pointVO.pointId } == true && !isLock) {
- return@forEach
- }
- val task = WorkTicketSendBO.DataBO.DataListBO(
- dataId = pointVO.pointId?.toInt(),
- equipRfidNo = pointVO.pointNfc,
- equipName = pointVO.pointName,
- target = if (isLock) 0 else 1
- )
- if (!isLock) {
- task.infoRfidNo = pointVO.lockNfc
- }
- pointVO.prePointId?.let {
- task.prevId = it.toInt()
- }
- // TODO partCode待补充
- taskList.add(task)
- }
- }
- dataBO.dataList = taskList
- bo.data = mutableListOf(dataBO)
- if (isLock) {
- // TODO 挂锁数组
- if (!lockList.isNullOrEmpty()) {
- bo.lockList = mutableListOf()
- lockList.forEachIndexed { index, s ->
- if (s.isNullOrEmpty()) {
- LogUtil.w("Lock nfc is null or empty")
- return@forEachIndexed
- }
- bo.lockList?.add(LockListBO(index + 1, s))
- }
- }
- }
- // TODO partList 待补充
- val jsonStr = Gson().toJson(bo)
- LogUtil.i("json : $jsonStr")
- return jsonStr
- }
- /**
- * 生成下空发工作票Json
- *
- * @param vo 工作票详情
- */
- fun generateEmptyTicketSendJson(): String {
- // 构造一个所有字段都为空/默认值的 WorkTicketSendBO
- val bo = WorkTicketSendBO(
- cardNo = "", // 空卡号
- effectiveTime = 0, // 默认有效时长
- password = "" // 空密码
- ).apply {
- // data 列表留空
- data = mutableListOf()
- // lockList 留空(如果字段非空,再设置为 emptyList())
- lockList = mutableListOf()
- }
- // 转成 JSON 并返回
- val jsonStr = Gson().toJson(bo)
- LogUtil.i("generateEmptyTicketJson: $jsonStr")
- return jsonStr
- }
- fun handleRsp(
- bleBean: BleBean,
- byteArray: ByteArray,
- isNeedLoading: Boolean = false,
- prepareDoneCallBack: ((Boolean, BleBean?) -> Unit)?
- ) {
- // TODO Token校验
- // val len = byteArray[2].toInt()
- // val token = byteArray.copyOfRange(len + 7, len + 11)
- // if (token.contentEquals(bleBean.token)) {
- // LogUtil.i("Token is right")
- // } else {
- // LogUtil.e("Token is wrong")
- // }
- when {
- // 获取令牌
- byteArray.startsWith(BleConst.RSP_GET_TOKEN) -> BleCmdManager.handleToken(
- bleBean.bleDevice, byteArray
- ) { isSuccess ->
- if (isSuccess) {
- //尝试使用命令作为心跳 ,获取token完成之后就要建立心跳了
- BleCmdManager.getPower(
- bleBean.bleDevice.mac, null
- )
- }
- }
- // 工作模式切换
- byteArray.startsWith(BleConst.RSP_SWITCH_MODE) -> {
- handleSwitchModeResult(byteArray, isNeedLoading) { res, job ->
- sendEventMsg(
- MsgEvent(
- MSG_EVENT_SWITCH_MODE, SwitchModeMsg(job.toInt(), res.toInt(), bleBean)
- )
- )
- }
- }
- // 工作票下发
- byteArray.startsWith(BleConst.RSP_SEND_WORK_TICKET) -> handleWorkTicketResult(
- bleBean, byteArray, isNeedLoading
- )
- // 获取设备当前状态
- byteArray.startsWith(BleConst.RSP_CURRENT_STATUS) -> BleCmdManager.handleCurrentStatus(
- byteArray
- ) {
- sendEventMsg(MsgEvent(MSG_EVENT_CURRENT_MODE, CurrentModeMsg(bleBean, it)))
- }
- // 获取设备工作票完成情况
- byteArray.startsWith(BleConst.RSP_WORK_TICKET_RESULT) && byteArray[3] == 0x02.toByte() -> handleTicketStatus(
- bleBean.bleDevice, byteArray, isNeedLoading
- )
- byteArray.startsWith(BleConst.RSP_POWER_STATUS) -> {
- val power = byteArray[4].toInt()
- ModBusController.updateKeyPower(power, bleBean.bleDevice.mac)
- LogUtil.i("电量(${bleBean.bleDevice.mac}):${power}")
- prepareDoneCallBack?.invoke(true, bleBean)
- if (power < 50) {//如果电量小于50就打开仓位充电
- ModBusController.controlKeyCharge(true, bleBean.bleDevice.mac) {
- LogUtil.i("钥匙: ${bleBean.bleDevice.mac} 开始充电")
- }
- }
- }
- }
- }
- /**
- * 工作模式切换结果
- * job : 0x01:工作模式 0x02:待机模式
- * res : 0x01:成功 0x02:失败
- */
- private fun handleSwitchModeResult(
- byteArray: ByteArray,
- isNeedLoading: Boolean = false,
- callBack: ((Byte, Byte) -> Unit)? = null
- ) {
- BleCmdManager.handleSwitchModeResult(byteArray) { job, res ->
- if (res == 0x01.toByte() && job == 0x01.toByte()) {
- LogUtil.i("切换工作模式成功")
- if (isNeedLoading) sendEventMsg(
- MsgEvent(
- MSG_EVENT_LOADING, LoadingMsg(false, "切换工作模式成功", null)
- )
- )
- } else if (res == 0x01.toByte() && job == 0x02.toByte()) {
- LogUtil.i("切换待机模式成功")
- if (isNeedLoading) sendEventMsg(
- MsgEvent(
- MSG_EVENT_LOADING, LoadingMsg(false, "切换待机模式成功", null)
- )
- )
- } else {
- LogUtil.e("切换模式失败 : ${job.toInt()} - ${res.toInt()}")
- if (isNeedLoading) sendEventMsg(
- MsgEvent(
- MSG_EVENT_LOADING, LoadingMsg(false, null, null)
- )
- )
- }
- callBack?.invoke(res, job)
- }
- }
- /**
- * 工作票下发结果
- * res:0x00:成功 0x01:失败 0x02:传输超时 0x0D:当前IDX超出范围 0x0E:当前数据CRC校验失败 0x14:JSON结构错误 0x63:未知错误
- */
- private fun handleWorkTicketResult(
- bleBean: BleBean, byteArray: ByteArray, isNeedLoading: Boolean = false
- ) {
- BleCmdManager.handleWorkTicketResult(bleBean, byteArray) { isSuccess, rst ->
- if (isNeedLoading) sendEventMsg(
- MsgEvent(
- MSG_EVENT_LOADING, LoadingMsg(false, null, null)
- )
- )
- if (isSuccess) {
- // 下发完毕,切换工作模式
- LogUtil.i("工作票下发完毕")
- if (isNeedLoading) sendEventMsg(
- MsgEvent(
- MSG_EVENT_LOADING, LoadingMsg(true, "切换钥匙为工作模式", null)
- )
- )
- Executor.delayOnIO(800) {
- //切换到工作模式
- switchWorkMode(bleBean.bleDevice, isNeedLoading)
- }
- } else {
- sendLoadingEventMsg(null, false)
- if (bleBean.retryCount < 3) {
- Executor.delayOnMain(500) {
- bleBean.retryCount++
- sendLoadingEventMsg(MyApplication.instance!!.getString(R.string.start_to_send_ticket))
- sendTicketWithRetry(bleBean.ticketSend!!, bleBean.bleDevice, isNeedLoading)
- }
- } else {
- ToastUtils.tip(R.string.send_ticket_fail)
- LogUtil.e("Send ticket fail")
- ModBusController.getKeyByMac(bleBean.bleDevice.mac)?.let { itKey ->
- mDeviceTakeList.removeIf { it.deviceType == DEVICE_TYPE_KEY && it.nfc == itKey.rfid }
- }
- }
- }
- }
- }
- /**
- * 获取当前钥匙的状态
- */
- fun getCurrentStatus(
- from: Int,
- bleDevice: BleDevice,
- retryCount: Int = 0,
- timeoutCallBack: ((Boolean) -> Unit)? = null
- ) {
- LogUtil.i("getCurrentStatus - ${bleDevice.mac} - from : $from")
- var isTimeout = true
- // 加1秒防止早于onWriteFailure开始处理导致多次处理
- Executor.delayOnMain((BleUtil.OPERATE_TIMEOUT + 1).toLong()) {
- if (isTimeout) {
- LogUtil.e("getCurrentStatus timeout : mac = ${bleDevice.mac}, retryCount = $retryCount")
- if (retryCount > 0) {
- if (from != 4) {
- val canConnect = BleSendDispatcher.canConnect()
- LogUtil.i("发送队列是否可以连接:${canConnect}")
- if (BleSendDispatcher.isConnected(bleDevice.mac)) {
- BleSendDispatcher.scheduleDisconnect(bleDevice.mac)
- }
- BleSendDispatcher.submit(bleDevice.mac) {
- getCurrentStatus(
- from, bleDevice, retryCount - 1, timeoutCallBack
- )
- }
- } else {
- BleReturnDispatcher.clearNoBusyConnectedDevice()
- BleReturnDispatcher.scheduleDisconnect(bleDevice.mac)
- BleReturnDispatcher.submit(bleDevice.mac) {
- getCurrentStatus(
- from, bleDevice, retryCount - 1, timeoutCallBack
- )
- }
- }
- } else {
- BleSendDispatcher.scheduleDisconnect(bleDevice.mac)
- BleReturnDispatcher.scheduleDisconnect(bleDevice.mac)
- ModBusController.getKeyByMac(bleDevice.mac)?.rfid?.let {
- addExceptionKey(it)
- timeoutCallBack?.invoke(true)
- }
- }
- }
- }
- BleCmdManager.getCurrentStatus(bleDevice, object : CustomBleWriteCallback() {
- override fun onWriteSuccess(
- bleDevice: BleDevice,
- characteristic: BluetoothGattCharacteristic,
- current: Int,
- total: Int,
- justWrite: ByteArray,
- data: ByteArray
- ) {
- LogUtil.i("getCurrentStatus success : ${bleDevice.mac}")
- isTimeout = false
- timeoutCallBack?.invoke(false)
- }
- override fun onWriteFailure(
- bleDevice: BleDevice,
- characteristic: BluetoothGattCharacteristic?,
- exception: BleException,
- current: Int,
- total: Int,
- justWrite: ByteArray?,
- data: ByteArray?,
- isTotalFail: Boolean
- ) {
- LogUtil.i("getCurrentStatus fail : ${bleDevice.mac}")
- isTimeout = false
- Executor.delayOnMain(1000) {
- getCurrentStatus(
- from, bleDevice,
- retryCount - 1, timeoutCallBack = timeoutCallBack
- )
- }
- }
- })
- }
- /**
- * 获取电池电量
- */
- fun getBatteryPower(bleDevice: BleDevice) {
- LogUtil.i("获取电池电量:${bleDevice.mac}")
- BleCmdManager.getPower(bleDevice.mac, object : CustomBleWriteCallback() {
- override fun onWriteSuccess(
- bleDevice: BleDevice,
- characteristic: BluetoothGattCharacteristic,
- current: Int,
- total: Int,
- justWrite: ByteArray,
- data: ByteArray
- ) {
- LogUtil.i("发送获取电池电量命令成功:${bleDevice.mac}")
- }
- override fun onWriteFailure(
- bleDevice: BleDevice,
- characteristic: BluetoothGattCharacteristic?,
- exception: BleException,
- current: Int,
- total: Int,
- justWrite: ByteArray?,
- data: ByteArray?,
- isTotalFail: Boolean
- ) {
- ThreadUtils.runOnIODelayed(500) {
- LogUtil.i("发送获取电池电量命令失败:${bleDevice.mac}")
- getBatteryPower(bleDevice)
- }
- }
- })
- }
- /**
- * 切换工作模式
- */
- private fun switchWorkMode(bleDevice: BleDevice, isNeedLoading: Boolean = false) {
- LogUtil.i("switchWorkMode - ${bleDevice.mac}")
- BleCmdManager.switchMode(STATUS_WORK, bleDevice, object : CustomBleWriteCallback() {
- override fun onWriteSuccess(
- bleDevice: BleDevice,
- characteristic: BluetoothGattCharacteristic,
- current: Int,
- total: Int,
- justWrite: ByteArray,
- data: ByteArray
- ) {
- LogUtil.i("switch mode work success : ${bleDevice.mac}")
- }
- override fun onWriteFailure(
- bleDevice: BleDevice,
- characteristic: BluetoothGattCharacteristic?,
- exception: BleException,
- current: Int,
- total: Int,
- justWrite: ByteArray?,
- data: ByteArray?,
- isTotalFail: Boolean
- ) {
- LogUtil.e("switch mode work fail : ${exception?.code} - ${exception?.description}")
- Executor.delayOnMain(500) {
- switchWorkMode(bleDevice, isNeedLoading)
- }
- }
- })
- }
- /**
- * 处理工作票完成情况
- */
- private fun handleTicketStatus(
- bleDevice: BleDevice, byteArray: ByteArray, isNeedLoading: Boolean = false
- ) {
- BleCmdManager.handleTicketStatus(bleDevice, byteArray) { ticketJson ->
- if (ticketJson.isNullOrEmpty()) {
- return@handleTicketStatus
- }
- if (isNeedLoading) sendEventMsg(
- MsgEvent(
- MSG_EVENT_LOADING, LoadingMsg(false, "工作票完成状态读取完成", null)
- )
- )
- LogUtil.i("Get ticket status complete : ${bleDevice.mac}")
- BleReturnDispatcher.removeBusy(bleDevice.mac)
- // TD:Ticket Done
- if (isNeedLoading) sendEventMsg(
- MsgEvent(
- MSG_EVENT_LOADING, LoadingMsg(false, "TD$ticketJson}", true)
- )
- )
- val workTicketGetBO = try {
- Gson().fromJson(ticketJson, WorkTicketGetBO::class.java)
- } catch (e: Exception) {
- null
- }
- if (workTicketGetBO == null) {
- ToastUtils.tip(R.string.ticket_data_error)
- return@handleTicketStatus
- }
- // 判断workTicketGetBO里是否有未完成的
- ThreadUtils.runOnIO {
- val finishedStatus = workTicketGetBO.hasFinished()
- LogUtil.i("作业票结束情况:${finishedStatus}")
- if (finishedStatus.first) {
- Executor.delayOnMain(500) {
- handleKeyReturn(bleDevice, workTicketGetBO, finishedStatus.second)
- //检查钥匙是否代取,如果是的话给钥匙
- val keyBean = ModBusController.getKeyByMac(bleDevice.mac)
- mDeviceTakeList.find { it.deviceType == DEVICE_TYPE_KEY && it.nfc == keyBean?.rfid }
- ?.let { itKey ->
- LogUtil.i("检查到存在待取钥匙:${itKey}")
- sendLoadingEventMsg(
- MyApplication.instance?.applicationContext!!.getString(
- R.string.ble_connecting
- )
- )
- handleGiveKey(itKey)
- }
- }
- } else {
- // 当前策略:作业票未完成禁止归还钥匙
- withContext(Dispatchers.Main) {
- showKeyReturnUploadDataForceDialog({
- handleKeyReturn(bleDevice, workTicketGetBO, finishedStatus.second)
- //检查钥匙是否代取,如果是的话给钥匙
- val keyBean = ModBusController.getKeyByMac(bleDevice.mac)
- mDeviceTakeList.find { it.deviceType == DEVICE_TYPE_KEY && it.nfc == keyBean?.rfid }
- ?.let { itKey ->
- sendLoadingEventMsg(
- MyApplication.instance?.applicationContext!!.getString(
- R.string.ble_connecting
- )
- )
- handleGiveKey(itKey)
- }
- }) {
- sendLoadingEventMsg(null, false)
- ToastUtils.tip(R.string.continue_the_ticket)
- BleReturnDispatcher.scheduleDisconnect(bleDevice.mac)
- // 打开卡扣,防止初始化的时候选择不处理钥匙导致无法使用
- val dock = ModBusController.getDockByKeyMac(bleDevice.mac)
- val keyBean = dock?.getKeyList()?.find { it.mac == bleDevice.mac }
- keyBean?.let {
- ModBusController.controlKeyBuckle(true, keyBean.isLeft, dock.addr)
- }
- }
- }
- }
- }
- }
- }
- /**
- * ticketFinished主要是后端的作业票是否已经结束,结束了,就直接修改状态就好了
- */
- private fun handleKeyReturn(
- bleDevice: BleDevice, workTicketGetBO: WorkTicketGetBO?, ticketFinished: Boolean
- ) {
- val dock = ModBusController.getDockByKeyMac(bleDevice.mac)
- val keyBean = dock?.getKeyList()?.find { it.mac == bleDevice.mac }
- keyBean?.let {
- ModBusController.controlKeyBuckle(false, keyBean.isLeft, dock.addr)
- }
- if (ticketFinished) {
- mDeviceTakeList.removeIf { it.nfc == keyBean?.rfid }
- switchReadyMode(bleDevice)
- } else {
- // 上报隔离点状态
- val keyNfc = ModBusController.getKeyByMac(bleDevice.mac)?.rfid ?: "key rfid lost"
- workTicketGetBO?.data?.forEach { data ->
- val updateList = mutableListOf<LockPointUpdateReqVO>()
- data.dataList?.filter { it.closed == 1 && it.status == it.target }
- ?.forEach { dataListDTO ->
- val updateVO = LockPointUpdateReqVO(
- data.taskCode?.toLong(),
- dataListDTO.infoRfidNo,
- dataListDTO.equipRfidNo,
- keyNfc,
- dataListDTO.target,
- dataListDTO.status
- )
- updateList.add(updateVO)
- }
- sendLoadingEventMsg(null, false)
- if (CAN_RETURN) {
- //如果需要上报的点位数据为空则直接上报钥匙归还
- if (updateList.isEmpty()) {
- mDeviceTakeList.removeIf { it.nfc == keyBean?.rfid }
- // 上报钥匙归还
- keyReturn(data.taskCode?.toLong()!!, keyNfc)
- switchReadyMode(bleDevice)
- return@forEach
- }
- // 上报点位钥匙绑定
- NetApi.updateLockPointBatch(updateList) { isSuccess, msg, code ->
- LogUtil.i("还锁操作:${isSuccess},${msg},${code}")
- if (isSuccess) {
- // 上报钥匙归还
- keyReturn(data.taskCode?.toLong()!!, keyNfc)
- data.taskCode?.toLong()?.let {
- sendEventMsg(
- MsgEvent(
- MSG_EVENT_UPDATE_TICKET_PROGRESS,
- UpdateTicketProgressMsg(it)
- )
- )
- }
- // 确认归还,切换为待机模式
- switchReadyMode(bleDevice)
- } else {
- ThreadUtils.runOnMain {
- // 当前策略:作业票未完成禁止归还钥匙
- showKeyReturnDialog {
- sendLoadingEventMsg(null, false)
- ToastUtils.tip(R.string.continue_the_ticket)
- BleReturnDispatcher.scheduleDisconnect(bleDevice.mac)
- // 打开卡扣,防止初始化的时候选择不处理钥匙导致无法使用
- if (workTicketGetBO.data?.all { it.dataList?.all { it.closed == 1 } == true } == true) {
- workTicketGetBO.data?.firstOrNull()?.taskCode?.toLong()
- ?.let {
- checkStepAndTicketDetailThenSendTicket(
- it, bleDevice.mac
- )
- }
- } else {
- val dock = ModBusController.getDockByKeyMac(bleDevice.mac)
- val keyBean =
- dock?.getKeyList()?.find { it.mac == bleDevice.mac }
- keyBean?.let {
- ModBusController.controlKeyBuckle(
- true, keyBean.isLeft, dock.addr
- )
- }
- }
- }
- }
- SPUtils.clearUpdateKeyReturn(MyApplication.instance!!)
- SPUtils.clearUpdateLockPoint(MyApplication.instance!!)
- }
- }
- } else {
- SPUtils.saveUpdateLockPoint(MyApplication.instance!!, updateList)
- SPUtils.saveUpdateKeyReturn(
- MyApplication.instance!!,
- UpdateKeyReturnBO(data.taskCode?.toLong()!!, keyNfc!!)
- )
- // 保存待发数据,切换为待机模式
- switchReadyMode(bleDevice)
- }
- }
- }
- }
- /**
- * 钥匙归还
- */
- private fun keyReturn(ticketId: Long, keyNfc: String) {
- NetApi.updateKeyReturn(
- ticketId,
- keyNfc,
- MyApplication.instance!!.serialNo()
- ) { isSuccess, msg, code ->
- if (!isSuccess) {
- if (msg == MyApplication.instance?.applicationContext!!.getString(
- R.string.ticket_lost
- )
- ) {
- sendEventMsg(
- MsgEvent(
- MsgEventConstants.MSG_EVENT_TICKET_FINISHED, null
- )
- )
- }
- SPUtils.clearUpdateKeyReturn(MyApplication.instance!!)
- ToastUtils.tip(R.string.key_return_success)
- } else {
- ToastUtils.tip(R.string.key_return_success)
- }
- }
- }
- /**
- * 处理虚拟钥匙取出,如果作业的全部点位已经上锁更新钥匙的状态使用
- */
- fun handleVirtualKeyGive(taskCode: Long, keyNfc: String, done: () -> Unit) {
- // 上报钥匙归还
- NetApi.updateKeyTake(taskCode, keyNfc, MyApplication.instance!!.serialNo()) { isSuccess ->
- if (isSuccess) {
- done()
- }
- }
- }
- /**
- * 处理虚拟钥匙归还,如果作业的全部点位已经上锁更新钥匙的状态使用
- */
- fun handleVirtualKeyReturn(taskCode: Long, keyNfc: String, done: () -> Unit) {
- // 上报钥匙归还
- NetApi.updateKeyReturn(
- taskCode, keyNfc, MyApplication.instance!!.serialNo()
- ) { isSuccess, msg, code ->
- if (!isSuccess) {
- if (msg == MyApplication.instance?.applicationContext!!.getString(
- R.string.ticket_lost
- )
- ) {
- sendEventMsg(
- MsgEvent(
- MsgEventConstants.MSG_EVENT_TICKET_FINISHED, null
- )
- )
- }
- SPUtils.clearUpdateKeyReturn(MyApplication.instance!!)
- } else {
- done()
- sendEventMsg(
- MsgEvent(
- MSG_EVENT_UPDATE_TICKET_PROGRESS, UpdateTicketProgressMsg(taskCode)
- )
- )
- }
- }
- }
- fun switchReadyMode(bleDevice: BleDevice) {
- BleCmdManager.switchMode(STATUS_READY, bleDevice, object : CustomBleWriteCallback() {
- override fun onWriteSuccess(
- bleDevice: BleDevice,
- characteristic: BluetoothGattCharacteristic,
- current: Int,
- total: Int,
- justWrite: ByteArray,
- data: ByteArray
- ) {
- LogUtil.i("switch mode ready success : ${bleDevice.mac}")
- }
- override fun onWriteFailure(
- bleDevice: BleDevice,
- characteristic: BluetoothGattCharacteristic?,
- exception: BleException,
- current: Int,
- total: Int,
- justWrite: ByteArray?,
- data: ByteArray?,
- isTotalFail: Boolean
- ) {
- LogUtil.e("switch mode ready fail : ${bleDevice.mac}")
- Executor.delayOnMain(300) {
- switchReadyMode(bleDevice)
- }
- }
- })
- }
- /**
- * 获取工作票完成情况
- */
- private fun getTicketStatus(
- bleDevice: BleDevice,
- isNeedLoading: Boolean = false,
- processCallback: ((Boolean) -> Unit)? = null
- ) {
- if (isNeedLoading) sendEventMsg(
- MsgEvent(
- MSG_EVENT_LOADING, LoadingMsg(true, "开始获取工作票", null)
- )
- )
- BleCmdManager.getTicketStatus(bleDevice, object : CustomBleWriteCallback() {
- override fun onWriteSuccess(
- bleDevice: BleDevice,
- characteristic: BluetoothGattCharacteristic,
- current: Int,
- total: Int,
- justWrite: ByteArray,
- data: ByteArray
- ) {
- if (isNeedLoading) sendEventMsg(
- MsgEvent(
- MSG_EVENT_LOADING, LoadingMsg(false, "工作票获取成功", null)
- )
- )
- LogUtil.i("getTicketStatus success")
- }
- override fun onWriteFailure(
- bleDevice: BleDevice,
- characteristic: BluetoothGattCharacteristic?,
- exception: BleException,
- current: Int,
- total: Int,
- justWrite: ByteArray?,
- data: ByteArray?,
- isTotalFail: Boolean
- ) {
- if (isNeedLoading) sendEventMsg(
- MsgEvent(
- MSG_EVENT_LOADING, LoadingMsg(false, "工作票获取失败", false)
- )
- )
- processCallback?.invoke(false)
- LogUtil.e("getTicketStatus fail")
- }
- })
- }
- /**
- * 添加待更新取出状态的设备
- */
- fun addDeviceTake(deviceType: Int, ticketId: Long, nfc: String?) {
- LogUtil.i("addDeviceTake : $deviceType - $ticketId - $nfc")
- mDeviceTakeList.removeIf { it.deviceType == deviceType && it.nfc == nfc }
- mDeviceTakeList.add(DeviceTakeUpdateBO(deviceType, ticketId, nfc!!))
- }
- fun removeDeviceTake(deviceType: Int, nfc: String?) {
- LogUtil.i("removeDeviceTake : $deviceType - $nfc")
- mDeviceTakeList.removeIf { it.deviceType == deviceType && it.nfc == nfc }
- }
- private fun handleDeviceTake(deviceTakeUpdateBO: DeviceTakeUpdateMsg, rfid: String? = null) {
- LogUtil.i("$deviceTakeUpdateBO")
- when (deviceTakeUpdateBO.deviceType) {
- // 钥匙
- 0 -> {
- mDeviceTakeList.find { it.deviceType == DEVICE_TYPE_KEY && it.nfc == deviceTakeUpdateBO.nfc }
- ?.let { info ->
- if (mDeviceTakeList.any { it.deviceType == DeviceConst.DEVICE_TYPE_LOCK && it.ticketId == info.ticketId }) {
- LogUtil.i("存在未取出的挂锁,不继续操作")
- return
- }
- sendLoadingEventMsg(null, false)
- NetApi.updateKeyTake(
- info.ticketId, info.nfc, MyApplication.instance?.serialNo()!!
- ) { isSuccess ->
- if (isSuccess) {
- mDeviceTakeList.removeIf {
- it.deviceType == DEVICE_TYPE_KEY && it.nfc == info.nfc && it.ticketId ==
- info.ticketId
- }
- sendEventMsg(
- MsgEvent(
- MSG_EVENT_UPDATE_TICKET_PROGRESS,
- UpdateTicketProgressMsg(info.ticketId)
- )
- )
- //钥匙取出之后重新再连一把钥匙待机
- ModBusController.getKeyByRfid(
- info.nfc
- )?.mac?.let {
- unregisterConnectListener(it)
- }
- //待机数不够就再连一把,但不能是原来那把
- ModBusController.getKeyByRfid(
- info.nfc
- )?.mac?.let {
- ThreadUtils.runOnIO {
- checkMyTodoForHandleKey(it)
- }
- }
- }
- }
- } ?: sendLoadingEventMsg(null, false)
- }
- // 挂锁
- 1 -> {
- mDeviceTakeList.find { it.deviceType == DEVICE_TYPE_LOCK && it.nfc == deviceTakeUpdateBO.nfc }
- ?.let { info ->
- NetApi.updateLockTake(
- mutableListOf(
- LockTakeUpdateReqVO(
- info.ticketId, info.nfc, MyApplication.instance?.serialNo()!!
- )
- )
- ) { isSuccess ->
- Executor.runOnMain {
- if (isSuccess == false) {
- LogUtil.e("Lock take report fail")
- ToastUtils.tip(R.string.lock_take_report_fail)
- SPUtils.saveTicketTakeLockException(info.ticketId)
- mDeviceTakeList.removeIf { it.deviceType == DEVICE_TYPE_LOCK && it.nfc == info.nfc }
- mDeviceTakeList.removeIf { it.deviceType == DEVICE_TYPE_KEY && it.ticketId == info.ticketId }
- sendLoadingEventMsg(null, false)
- return@runOnMain
- }
- // 检查是不是要发钥匙了
- mDeviceTakeList.removeIf { it.deviceType == DEVICE_TYPE_LOCK && it.nfc == info.nfc }
- // 检查当前工作票是否取完挂锁
- if (mDeviceTakeList.any { it.deviceType == DEVICE_TYPE_LOCK && it.ticketId == info.ticketId }) {
- LogUtil.i("Waiting all locks to take out")
- sendLoadingEventMsg(
- MyApplication.instance?.applicationContext?.getString(
- R.string.take_out_lock_tip,
- mDeviceTakeList.count { it.deviceType == DEVICE_TYPE_LOCK && it.ticketId == info.ticketId })
- )
- ToastUtils.tip(R.string.take_out_rest_locks)
- return@runOnMain
- } else {
- LogUtil.i("All locks are taken")
- sendLoadingEventMsg(null, false)
- }
- if (SPUtils.getTicketTakeLockException(info.ticketId)) {
- ToastUtils.tip(R.string.current_ticket_report_lock_take_exception_tip)
- return@runOnMain
- }
- // 检查有无当前工作票的钥匙
- mDeviceTakeList.find { it.deviceType == DEVICE_TYPE_KEY && it.ticketId == info.ticketId }
- ?.let { itKey ->
- sendLoadingEventMsg(
- MyApplication.instance?.applicationContext!!.getString(
- R.string.ble_connecting
- )
- )
- handleGiveKey(itKey)
- }
- }
- }
- }
- }
- }
- }
- /**
- * 分配钥匙
- */
- private fun handleGiveKey(deviceTakeUpdateBO: DeviceTakeUpdateBO) {
- getBleDeviceByMac(ModBusController.getKeyByRfid(deviceTakeUpdateBO.nfc)?.mac)?.let {
- getCurrentStatus(
- 2,
- getBleDeviceByMac(ModBusController.getKeyByRfid(deviceTakeUpdateBO.nfc)?.mac)!!.bleDevice
- ) {
- if (!it) {
- return@getCurrentStatus
- }
- LogUtil.w("handleGiveKey timeout")
- removeDeviceTake(DEVICE_TYPE_KEY, deviceTakeUpdateBO.nfc)
- checkEquipCount(0, true) { keyPair, lockMap ->
- if (keyPair == null) {
- ThreadUtils.runOnMain {
- val tipDialog = TipDialog(SIKCore.getApplication())
- tipDialog.setTip(
- SIKCore.getApplication().getString(R.string.key_take_error_tip)
- )
- tipDialog.setConfirmListener {
- tipDialog.dismiss()
- sendEventMsg(
- MsgEvent(
- MSG_EVENT_DEVICE_EXCEPTION,
- DeviceExceptionMsg(DEVICE_TYPE_KEY, deviceTakeUpdateBO.nfc)
- )
- )
- }
- tipDialog.show()
- }
- } else {
- addDeviceTake(
- DEVICE_TYPE_KEY, deviceTakeUpdateBO.ticketId, keyPair.second?.rfid!!
- )
- handleGiveKey(
- DeviceTakeUpdateBO(
- DEVICE_TYPE_KEY, deviceTakeUpdateBO.ticketId, keyPair.second?.rfid!!
- )
- )
- }
- }
- }
- } ?: run {
- ThreadUtils.runOnMain {
- ActivityTracker.getCurrentActivity()?.let {
- val tipDialog = TipDialog(it)
- tipDialog.setTip(
- SIKCore.getApplication().getString(R.string.key_take_error_tip)
- )
- tipDialog.setConfirmListener {
- tipDialog.dismiss()
- sendEventMsg(
- MsgEvent(
- MSG_EVENT_DEVICE_EXCEPTION,
- DeviceExceptionMsg(DEVICE_TYPE_KEY, deviceTakeUpdateBO.nfc)
- )
- )
- }
- tipDialog.show()
- }
- }
- }
- }
- /**
- * 根据当前模式进行处理
- */
- private fun handleCurrentMode(currentModeMsg: CurrentModeMsg) {
- when (currentModeMsg.mode) {
- // 工作模式
- 0x01.toByte() -> {
- // 读工作票
- getTicketStatusBusiness(currentModeMsg.bleBean.bleDevice.mac)
- }
- // 待机模式
- 0x02.toByte() -> {
- // 根据情况看是否需要下发工作票
- ModBusController.getKeyByMac(currentModeMsg.bleBean.bleDevice.mac)?.let { key ->
- // 判断是否有待取的钥匙
- val updateBo =
- mDeviceTakeList.find { it.deviceType == DEVICE_TYPE_KEY && key.rfid == it.nfc }
- if (mDeviceTakeList.any { it.deviceType == DEVICE_TYPE_LOCK && it.ticketId == updateBo?.ticketId }) {
- //todo 如果有钥匙待取但是对应的作业票的锁还有的,就不发
- return
- }
- updateBo?.let { itBO ->
- if (BleReturnDispatcher.isConnected(currentModeMsg.bleBean.bleDevice.mac)) {
- LogUtil.i("当前钥匙在归还队列,断开连接")
- BleReturnDispatcher.scheduleDisconnect(currentModeMsg.bleBean.bleDevice.mac)
- }
- if (BleSendDispatcher.isConnected(currentModeMsg.bleBean.bleDevice.mac)) {
- LogUtil.i("当前钥匙已在发送队列连接")
- checkAndSendTicket(currentModeMsg, itBO)
- } else {
- LogUtil.i("当前钥匙未加入发送队列,连接后发送")
- BleSendDispatcher.submit(currentModeMsg.bleBean.bleDevice.mac) {
- checkAndSendTicket(currentModeMsg, itBO)
- }
- }
- } ?: let {
- ModBusController.updateKeyReadyStatus(
- currentModeMsg.bleBean.bleDevice.mac, true, 4
- )
- sendLoadingEventMsg(null, false)
- BleReturnDispatcher.scheduleDisconnect(currentModeMsg.bleBean.bleDevice.mac)
- //连上之后没有工作票要下发就断开 看是否还有设备等待连接,没有就不断开,有就让路,一般是初始化的时候
- ThreadUtils.runOnIO {
- checkMyTodoForHandleKey(currentModeMsg.bleBean.bleDevice.mac)
- }
- }
- } ?: let {
- ModBusController.updateKeyReadyStatus(
- currentModeMsg.bleBean.bleDevice.mac, true, 4
- )
- sendLoadingEventMsg(null, false)
- BleReturnDispatcher.scheduleDisconnect(currentModeMsg.bleBean.bleDevice.mac)
- //连上之后没有工作票要下发就断开 看是否还有设备等待连接,没有就不断开,有就让路,一般是初始化的时候
- ThreadUtils.runOnIO {
- checkMyTodoForHandleKey(currentModeMsg.bleBean.bleDevice.mac)
- }
- }
- }
- // 故障模式
- 0x03.toByte() -> {
- // TODO 上报?
- ToastUtils.tip(
- "${currentModeMsg.bleBean.bleDevice.mac} : " + "${CommonUtils.getStr(R.string.key_is_in_failure_mode)}"
- )
- }
- }
- }
- /**
- * 检查并下发作业票
- */
- private fun checkAndSendTicket(currentModeMsg: CurrentModeMsg, itBO: DeviceTakeUpdateBO) {
- NetApi.getStepDetail(itBO.ticketId) {
- var step = 0
- it?.filter { it.stepStatus == "1" }
- ?.maxByOrNull { it.stepIndex!! }?.stepIndex?.let {
- step = it
- }
- NetApi.getTicketDetail(itBO.ticketId) { ticketDetail, _ ->
- if (ticketDetail == null) {
- return@getTicketDetail
- }
- val role = ticketDetail?.ticketUserVOList?.find {
- it.userId == SPUtils.getLoginUser(MyApplication.instance?.applicationContext!!)?.userId && it.userType == USER_TYPE_LOCKER
- }
- if (role == null) {
- ToastUtils.tip(R.string.you_are_not_locker_tip)
- return@getTicketDetail
- }
- if (step == 4) { // 上锁工作票
- sendTicketBusiness(
- true,
- currentModeMsg.bleBean.bleDevice.mac,
- ticketDetail,
- ticketDetail.ticketLockVOList?.filter {
- ticketDetail.ticketPointsVOList?.mapNotNull { it.lockId }
- ?.contains(it.lockId) != true
- }?.map { it.lockNfc }?.toMutableList(),
- ActivityUtils.currentActivity() as BaseActivity<*>,
- true
- )
- } else if (step == 7) { // 解锁工作票
- sendTicketBusiness(
- false,
- currentModeMsg.bleBean.bleDevice.mac,
- ticketDetail,
- null,
- ActivityUtils.currentActivity() as BaseActivity<*>,
- true
- )
- }
- }
- }
- }
- /**
- * 检查步骤和作业票详情并且下发作业票
- */
- private fun checkStepAndTicketDetailThenSendTicket(ticketId: Long, mac: String) {
- NetApi.getStepDetail(ticketId) {
- var step = 0
- it?.filter { it.stepStatus == "1" }?.maxByOrNull { it.stepIndex!! }?.stepIndex?.let {
- step = it
- }
- NetApi.getTicketDetail(ticketId) { ticketDetail, _ ->
- if (ticketDetail == null) {
- return@getTicketDetail
- }
- val role = ticketDetail?.ticketUserVOList?.find {
- it.userId == SPUtils.getLoginUser(MyApplication.instance?.applicationContext!!)?.userId && it.userType == USER_TYPE_LOCKER
- }
- if (role == null) {
- ToastUtils.tip(R.string.you_are_not_locker_tip)
- return@getTicketDetail
- }
- if (step == 4) { // 上锁工作票
- sendTicketBusiness(
- true,
- mac,
- ticketDetail,
- ticketDetail.ticketLockVOList?.filter {
- ticketDetail.ticketPointsVOList?.mapNotNull { it.lockId }
- ?.contains(it.lockId) != true
- }?.map { it.lockNfc }?.toMutableList(),
- ActivityUtils.currentActivity() as BaseActivity<*>,
- true
- )
- } else if (step == 7) { // 解锁工作票
- sendTicketBusiness(
- false,
- mac,
- ticketDetail,
- null,
- ActivityUtils.currentActivity() as BaseActivity<*>,
- true
- )
- }
- }
- }
- }
- fun submitKeyData(context: Context) {
- if (!CAN_RETURN) return
- val updateList = SPUtils.getUpdateLockPoint(context)
- if (updateList.isNotEmpty()) {
- NetApi.updateLockPointBatch(updateList) { isSuccess, msg, code ->
- LogUtil.i("submitKeyData还锁操作:${isSuccess},${msg},${code}")
- if (isSuccess || code == 500) {
- SPUtils.clearUpdateLockPoint(context)
- SPUtils.clearUpdateKeyReturn(context)
- }
- }
- }
- val returnList =
- SPUtils.getUpdateKeyReturn(context).filter { it.keyNfc.isNotEmpty() }.toMutableList()
- if (returnList.isEmpty()) {
- return
- }
- val itemsToRemove = returnList.toList()
- var count = 0
- itemsToRemove.forEach { itData ->
- NetApi.updateKeyReturn(
- itData.ticketId, itData.keyNfc, context.serialNo()
- ) { isSuccess, msg, code ->
- count++
- if (!isSuccess) {
- if (msg == MyApplication.instance?.applicationContext!!.getString(
- R.string.ticket_lost
- )
- ) {
- sendEventMsg(
- MsgEvent(
- MsgEventConstants.MSG_EVENT_TICKET_FINISHED, null
- )
- )
- }
- SPUtils.clearUpdateKeyReturn(MyApplication.instance!!)
- }
- }
- }
- }
- fun sendLoadingEventMsg(str: String?, isShow: Boolean = true) {
- sendEventMsg(MsgEvent(MSG_EVENT_LOADING, LoadingMsg(isShow, str, false)))
- }
- fun logout(context: Context) {
- reConnectKey()
- NetApi.logout()
- // 关所有有设备的卡扣
- 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>
- ModBusController.controlLockBuckle(false, dockBean.addr, hasLockIdxList)
- ModBusController.controlLockBuckle(true, dockBean.addr, noLockIdxList)
- }
- dockList.filter { it.type == DOCK_TYPE_KEY || it.type == DOCK_TYPE_PORTABLE }
- .forEach { dockBean ->
- dockBean.getKeyList().forEach { key ->
- if (key.isExist) {
- NetApi.getKeyInfo(key.rfid.toString()) {
- if (it != null && !it.macAddress.isNullOrEmpty()) {
- ModBusController.updateKeyMac(
- dockBean.addr, key.isLeft, it.macAddress
- )
- ModBusController.controlKeyBuckle(
- false, key.isLeft, dockBean.addr
- )
- } else {
- ModBusController.controlKeyBuckle(
- true, key.isLeft, dockBean.addr
- )
- }
- }
- } else {
- ModBusController.controlKeyBuckle(true, key.isLeft, dockBean.addr)
- }
- }
- }
- BleSendDispatcher.disconnectAll(60_0000L)
- sendLoadingEventMsg(null, false)
- context.startActivity(Intent(context, LoginActivity::class.java).apply {
- flags = Intent.FLAG_ACTIVITY_NEW_TASK
- })
- }
- /**
- * 钥匙重新连接,清除内部作业票,清除所有代取设备重新分配
- */
- private fun reConnectKey() {
- val keyList = mDeviceTakeList.filter { it.deviceType == DEVICE_TYPE_KEY }
- // 不拿的设备不归你,下次登录重新按需分配
- // 尽早clear,防止触发handleCurrentMode导致重新下发作业票
- mDeviceTakeList.clear()
- // 连接后直接切换待机模式,让钥匙作业票失效并且重新准备完毕
- keyList.forEach {
- val mac = ModBusController.getKeyByRfid(it.nfc)?.mac
- if (mac == null) {
- NetApi.getKeyInfo(it.nfc) { keyInfo ->
- keyInfo?.macAddress?.let { itMac ->
- registerConnectListener(itMac, isSend = true) { isDone, bleBean ->
- if (isDone && bleBean != null) {
- switchReadyMode(bleBean.bleDevice)
- }
- }
- }
- }
- } else {
- registerConnectListener(mac, isSend = true) { isDone, bleBean ->
- if (isDone && bleBean != null) {
- switchReadyMode(bleBean.bleDevice)
- }
- }
- }
- }
- }
- /**
- * 强制使用setValue,防止postValue造成数据丢失
- */
- fun sendEventMsg(msgEvent: MsgEvent) {
- Executor.runOnMain {
- mEventBus.value = msgEvent
- }
- }
- fun addExceptionKey(rfid: String) {
- LogUtil.w("addExceptionKey: $rfid")
- if (mExceptionKeyList.contains(rfid)) {
- return
- }
- mExceptionKeyList.add(rfid)
- }
- fun removeExceptionKey(key: String) {
- LogUtil.i("removeExceptionKey: $key")
- mExceptionKeyList.remove(key)
- }
- }
|