#
Junjie
2025-01-06 0ac76f7d8101903e1d050116f7d3835ce1303dfa
#
52个文件已修改
27个文件已添加
101个文件已删除
2 文件已重命名
25467 ■■■■ 已修改文件
src/main/java/com/zy/asrs/controller/ConsoleController.java 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/CrnController.java 527 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/ForkLiftController.java 243 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/LiftController.java 380 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/MonitorController.java 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/ShuttleController.java 347 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/SiteController.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/enums/CrnStatusType.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/param/CrnDemoParam.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/param/CrnOperatorParam.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/param/SteModeParam.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/param/SteOperatorParam.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/vo/CommandLogVo.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/vo/CrnDetailVo.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/vo/CrnLatestDataVo.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/vo/CrnMsgTableVo.java 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/vo/CrnStateTableVo.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/vo/LiftStateTableVo.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/vo/ShuttleMsgTableVo.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/vo/ShuttleStateTableVo.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/vo/SteMsgTableVo.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/vo/SteSensorDataVo.java 266 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/domain/vo/SteStateTableVo.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/BasCrnError.java 164 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/BasCrnOpt.java 334 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/BasCrnp.java 436 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/BasErrLog.java 456 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/BasLift.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/BasShuttle.java 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/BasSte.java 197 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/BasSteErr.java 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/BasSteErrLog.java 266 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/BasSteOpt.java 341 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/LocMast.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/StaDesc.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/WrkCharge.java 340 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/WrkMast.java 249 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/WrkMastLog.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/BasCrnErrorMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/BasCrnOptMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/BasCrnpMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/BasErrLogMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/BasSteErrLogMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/BasSteErrMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/BasSteMapper.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/BasSteOptMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/LocMastMapper.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/WrkChargeMapper.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/WrkMastMapper.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/BasCrnOptService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/BasCrnpService.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/BasErrLogService.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/BasSteErrLogService.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/BasSteErrService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/BasSteOptService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/BasSteService.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/WrkChargeService.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/WrkMastService.java 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/BasCrnOptServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/BasCrnpServiceImpl.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/BasDevpServiceImpl.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/BasErrLogServiceImpl.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/BasSteErrLogServiceImpl.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/BasSteErrServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/BasSteOptServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/BasSteServiceImpl.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java 4692 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/WrkChargeServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/WrkMastServiceImpl.java 98 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/ShuttlePowerEarlyWarning.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/utils/Utils.java 433 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/ws/ConsoleWebSocket.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/ExecuteSupport.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/model/MapNode.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/model/NavigateNode.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/model/ShuttleOperaResult.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/service/CommonService.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/utils/ForkLiftOperaUtils.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/utils/ForkLiftUtils.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/utils/NavigateMapData.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/utils/NavigatePositionConvert.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/utils/NavigateSolution.java 277 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/utils/NavigateUtils.java 272 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/utils/News.java 195 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/utils/NyHttpUtils.java 368 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/utils/NyLiftUtils.java 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/utils/NyShuttleOperaUtils.java 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/utils/ShuttleOperaUtils.java 355 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/CrnThread.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/MainProcess.java 60 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/ServerBootstrap.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/ThreadHandler.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/action/ForkLiftAction.java 155 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/action/ShuttleAction.java 668 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/cache/OutputQueue.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/dispatcher/ShuttleDispatchUtils.java 247 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/CrnFingerPosType.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/CrnForkPosType.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/CrnLiftPosType.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/CrnModeType.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/CrnStatusType.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/CrnTaskModeType.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/ForkLiftConfirmType.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/ForkLiftIoModeType.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/ForkLiftProtocolStatusType.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/ForkLiftTaskModeType.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/LiftLevType.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/LiftNotReadyType.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/LiftProtocolStatusType.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/LocStsType.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/MapNodeType.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/NyLiftTaskModelType.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/RedisKeyType.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/ShuttleChargeType.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/ShuttleCommandModeType.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/ShuttleErrorCodeType.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/ShuttlePlcInputStatusType.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/ShuttlePlcOutputStatusType.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/ShuttleTaskModeType.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/ShuttleTaskNoType.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/SlaveType.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/SteABType.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/SteChargeType.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/SteHisTaskStatusType.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/SteLocaType.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/SteStatusType.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/SteTaskModeType.java 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/enums/WrkStsType.java 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/CommandResponse.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/CrnSlave.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/Devp2Slave.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/ForkLiftSlave.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/PythonResult.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/PythonSimilarityResult.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/SteSlave.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/command/CrnCommand.java 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/command/ForkLiftCommand.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/command/LiftAssignCommand.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/command/LiftCommand.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/command/NyLiftCommand.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/command/NyShuttleHttpCommand.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/command/ShuttleAssignCommand.java 38 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/command/ShuttleCommand.java 84 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/command/ShuttleRedisCommand.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/command/SteCommand.java 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/param/ShuttleMoveLocParam.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/CrnError1.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/CrnError2.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/CrnError3.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/CrnError4.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/CrnError5.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/CrnError6.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/CrnProtocol.java 264 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/CrnTemp1.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/ForkLiftProtocol.java 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/ForkLiftStaProtocol.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/LiftProtocol.java 243 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/LiftStaProtocol.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/NyShuttleProtocol.java 608 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/ShuttleProtocol.java 343 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/SteProtocol.java 556 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/properties/SlaveProperties.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/ForkLiftThread.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/LiftThread.java 1048 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/NyShuttleThread.java 899 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/ShuttleThread.java 1285 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/SiemensCrnThread.java 465 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/SteThread.java 546 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/impl/NyShuttleThread.java 1150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/thread/impl/ZyForkLiftThread.java 277 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application.yml 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/BasCrnErrorMapper.xml 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/BasCrnpMapper.xml 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/BasMapMapper.xml 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/BasShuttleMapper.xml 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/BasSteErrLogMapper.xml 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/BasSteErrMapper.xml 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/BasSteMapper.xml 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/BasSteOptMapper.xml 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/LocMastMapper.xml 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/WrkChargeMapper.xml 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/WrkMastMapper.xml 95 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/ConsoleController.java
@@ -3,10 +3,8 @@
import com.alibaba.fastjson.JSON;
import com.core.annotations.ManagerAuth;
import com.core.common.Arith;
import com.core.common.BaseRes;
import com.core.common.Cools;
import com.core.common.R;
import com.zy.asrs.domain.enums.CrnStatusType;
import com.zy.asrs.domain.enums.SiteStatusType;
import com.zy.asrs.domain.param.SystemSwitchParam;
import com.zy.asrs.domain.vo.*;
@@ -20,36 +18,26 @@
import com.zy.common.CodeRes;
import com.zy.common.model.MapNode;
import com.zy.common.model.enums.NavigationMapType;
import com.zy.common.utils.Http;
import com.zy.common.utils.NavigateMapData;
import com.zy.common.utils.RedisUtil;
import com.zy.core.CrnThread;
import com.zy.core.DevpThread;
import com.zy.core.Slave;
import com.zy.core.cache.OutputQueue;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.CrnModeType;
import com.zy.core.enums.RedisKeyType;
import com.zy.core.enums.SlaveType;
import com.zy.core.model.CrnSlave;
import com.zy.core.model.DevpSlave;
import com.zy.core.model.protocol.CrnProtocol;
import com.zy.core.model.protocol.StaProtocol;
import com.zy.core.properties.SlaveProperties;
import com.zy.core.properties.SystemProperties;
import com.zy.core.thread.BarcodeThread;
import com.zy.core.thread.ScaleThread;
import com.zy.core.thread.SiemensCrnThread;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.*;
/**
@@ -125,50 +113,6 @@
            vo.setWorkNo(staProtocol.getWorkNo()); // 工作号
            vo.setSiteStatus(SiteStatusType.process(staProtocol));  // 状态
            vos.add(vo);
        }
        return R.ok().add(vos);
    }
    @PostMapping("/latest/data/crn")
    @ManagerAuth(memo = "堆垛机实时数据")
    public R crnLatestData(){
        List<CrnLatestDataVo> vos = new ArrayList<>();
        for (CrnSlave crn : slaveProperties.getCrn()) {
            // 获取堆垛机信息
            CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crn.getId());
            if (crnThread == null) {
                continue;
            }
            CrnProtocol crnProtocol = crnThread.getCrnProtocol();
            if (crnProtocol == null) {
                continue;
            }
            CrnLatestDataVo vo = new CrnLatestDataVo();
            vo.setCrnId(crn.getId());   //  堆垛机编号
//            Short totalBay = locMastMapper.selectTotalBay();
            vo.setOffset((double) new Random().nextInt(560));     //  堆垛机偏移量
            vo.setBay((short) (crnProtocol.getBay() - crn.getOffset()));    //  当前列
            /**
             * 堆垛机状态判断
             */
            if (crn.getId() == 1 && crnProtocol.getAlarm() > 0) {
                vo.setCrnStatus(CrnStatusType.MACHINE_ERROR);
            } else {
                if (crnProtocol.getTaskNo()>0) {
                    WrkMast wrkMast = wrkMastService.selectById(crnProtocol.getTaskNo());
                    if (wrkMast != null) {
                        vo.setCrnStatus(CrnStatusType.process(wrkMast.getIoType()));
                    } else {
                        vo.setCrnStatus(crnProtocol.modeType.equals(CrnModeType.AUTO)? CrnStatusType.MACHINE_AUTO: CrnStatusType.MACHINE_UN_AUTO);
                    }
                } else {
                    vo.setCrnStatus(crnProtocol.modeType.equals(CrnModeType.AUTO)? CrnStatusType.MACHINE_AUTO: CrnStatusType.MACHINE_UN_AUTO);
                }
            }
            vos.add(vo);
        }
        return R.ok().add(vos);
    }
@@ -256,38 +200,6 @@
    }
    @PostMapping("/crn/detail")
    @ManagerAuth(memo = "堆垛机设备数据详情")
    public R crnDetail(@RequestParam Integer crnNo){
        if (Cools.isEmpty(crnNo)){
            return R.parse(CodeRes.EMPTY);
        }
        CrnDetailVo vo = new CrnDetailVo();
        for (CrnSlave crnSlave : slaveProperties.getCrn()) {
            if (crnSlave.getId().equals(crnNo)) {
                SiemensCrnThread crnThread = (SiemensCrnThread) SlaveConnection.get(SlaveType.Crn, crnSlave.getId());
                CrnProtocol crnProtocol = crnThread.getCrnProtocol();
                vo.setCrnNo(crnNo);
                vo.setWorkNo(crnProtocol.getTaskNo());
                if (crnProtocol.getTaskNo() > 0) {
                    WrkMast wrkMast = wrkMastService.selectById(crnProtocol.getTaskNo());
                    if (wrkMast != null) {
                        vo.setSourceStaNo(wrkMast.getSourceStaNo$());
                        vo.setStaNo(wrkMast.getStaNo$());
                        vo.setWrkSts(wrkMast.getWrkSts$());   // 工作状态
                        vo.setIoType(wrkMast.getIoType$());   //  入出库类型
                        vo.setSourceLocNo(wrkMast.getSourceLocNo$());
                        vo.setLocNo(wrkMast.getLocNo$());
                        vo.setCrnStatus(crnProtocol.getStatusType().desc);
                        vo.setError("");    // todo
                    }
                }
                return R.ok().add(vo);
            }
        }
        return R.error();
    }
    @Deprecated
    @PostMapping("/site/update")
    @ManagerAuth(memo = "输送设备数据修改")
@@ -303,15 +215,7 @@
    }
    @GetMapping("/barcode/output/site")
    public R crnOutput(){
//        StringBuilder str = new StringBuilder();
//        String s;
//        int i = 0;
//        while((s = OutputQueue.CRN.poll()) != null && i <=32) {
//            str.append("\n").append(s);
//            i++;
//        }
//        return R.ok().add(str.toString());
    public R barcodeOutput(){
        return R.ok().add(JSON.toJSONString(new ArrayList<>(OutputQueue.BARCODE)));
    }
src/main/java/com/zy/asrs/controller/CrnController.java
File was deleted
src/main/java/com/zy/asrs/controller/ForkLiftController.java
New file
@@ -0,0 +1,243 @@
package com.zy.asrs.controller;
import com.alibaba.fastjson.JSON;
import com.core.annotations.ManagerAuth;
import com.core.common.Cools;
import com.core.common.R;
import com.zy.asrs.domain.vo.*;
import com.zy.asrs.entity.BasLift;
import com.zy.asrs.service.BasLiftService;
import com.zy.common.utils.RedisUtil;
import com.zy.core.cache.OutputQueue;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.ForkLiftProtocolStatusType;
import com.zy.core.enums.RedisKeyType;
import com.zy.core.enums.SlaveType;
import com.zy.core.model.ForkLiftSlave;
import com.zy.core.model.command.*;
import com.zy.core.model.protocol.ForkLiftProtocol;
import com.zy.core.properties.SlaveProperties;
import com.zy.core.thread.ForkLiftThread;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
/**
 * 提升机接口
 */
@Slf4j
@RestController
@RequestMapping("/lift")
public class ForkLiftController {
    @Autowired
    private SlaveProperties slaveProperties;
    @Autowired
    private BasLiftService basLiftService;
    @Autowired
    private RedisUtil redisUtil;
    @PostMapping("/table/lift/state")
    @ManagerAuth(memo = "提升机信息表")
    public R liftStateTable(){
        List<LiftStateTableVo> list = new ArrayList<>();
        for (ForkLiftSlave slave : slaveProperties.getForkLift()) {
            // 表格行
            LiftStateTableVo vo = new LiftStateTableVo();
            vo.setLiftNo(slave.getId());   //提升机号
            list.add(vo);
            // 获取提升机信息
            ForkLiftThread forkLiftThread = (ForkLiftThread) SlaveConnection.get(SlaveType.ForkLift, slave.getId());
            if (forkLiftThread == null) {
                vo.setProtocolStatus(ForkLiftProtocolStatusType.NONE.id);//离线
                continue;
            }
            ForkLiftProtocol forkLiftProtocol = forkLiftThread.getStatus();
            if (forkLiftProtocol == null || forkLiftProtocol.getLiftNo()==null) {
                continue;
            }
            vo.setTaskNo(forkLiftProtocol.getTaskNo().shortValue());  //  任务号
            vo.setProtocolStatus(forkLiftProtocol.getProtocolStatusType().id);
        }
        return R.ok().add(list);
    }
    @PostMapping("/table/lift/msg")
    @ManagerAuth(memo = "提升机数据表")
    public R liftMsgTable(){
        List<LiftMsgTableVo> list = new ArrayList<>();
        for (ForkLiftSlave slave : slaveProperties.getForkLift()) {
            // 表格行
            LiftMsgTableVo vo = new LiftMsgTableVo();
            vo.setLiftNo(slave.getId());   //  提升机号
            list.add(vo);
            // 获取提升机信息
            ForkLiftThread forkLiftThread = (ForkLiftThread) SlaveConnection.get(SlaveType.ForkLift, slave.getId());
            if (forkLiftThread == null) {
                continue;
            }
            ForkLiftProtocol forkLiftProtocol = forkLiftThread.getStatus();
            if (forkLiftProtocol == null) {
                continue;
            }
            vo.setWorkNo(forkLiftProtocol.getTaskNo().intValue());//任务号
            vo.setPakMk(forkLiftProtocol.getPakMk()?"Y" : "N");    // 作业标记
        }
        return R.ok().add(list);
    }
    @PostMapping("/output/lift")
    @ManagerAuth
    public R liftOutput(){
        StringBuilder str = new StringBuilder();
        String s;
        int i = 0;
        while((s = OutputQueue.LIFT.poll()) != null && i <=10) {
            str.append("\n").append(s);
            i++;
        }
        return R.ok().add(str.toString());
    }
    @GetMapping("/detl/{liftNo}")
    public R liftDetl(@PathVariable("liftNo") Integer liftNo){
        LiftDataVo vo = new LiftDataVo();
        for (ForkLiftSlave liftSlave : slaveProperties.getForkLift()) {
            if (liftNo.equals(liftSlave.getId())) {
                vo.setLiftNo(liftSlave.getId());
                BasLift basLift = basLiftService.selectById(liftSlave.getId());
                if (!Cools.isEmpty(basLift)) {
                    vo.setWorkNo(basLift.getWrkNo());
                    vo.setPakMk(basLift.getPakMk());
                }
                break;
            }
        }
        return R.ok().add(vo);
    }
    @GetMapping("/sensor/detl/{liftNo}")
    public R liftSensorDetl(@PathVariable("liftNo") Integer liftNo){
        LiftSensorDataVo vo = new LiftSensorDataVo();
        for (ForkLiftSlave liftSlave : slaveProperties.getForkLift()) {
            if (liftNo.equals(liftSlave.getId())) {
                vo.setLiftNo(liftSlave.getId());
                // 获取提升机信息
                ForkLiftThread forkLiftThread = (ForkLiftThread) SlaveConnection.get(SlaveType.ForkLift, liftSlave.getId());
                if (forkLiftThread == null) {
                    return R.error("设备不在线");
                }
                ForkLiftProtocol forkLiftProtocol = forkLiftThread.getStatus();
                if (forkLiftProtocol == null) {
                    return R.error("设备不在线");
                }
                break;
            }
        }
        return R.ok().add(vo);
    }
    @PostMapping("/detl/update")
    @ManagerAuth(memo = "修改数据")
    public R liftUpdate(@RequestParam Integer liftNo,
                        @RequestParam Short workNo,
                        @RequestParam String pakMk,
                        @RequestParam Integer token) {
        ForkLiftThread forkLiftThread = (ForkLiftThread) SlaveConnection.get(SlaveType.ForkLift, liftNo);
        if (forkLiftThread == null) {
            return R.error("plc已掉线");
        }
        ForkLiftProtocol forkLiftProtocol = forkLiftThread.getStatus();
        if (forkLiftProtocol == null) {
            return R.error("plc已掉线");
        }
        if (workNo != null) {
            forkLiftThread.setSyncTaskNo(workNo.intValue());
        }
        return R.ok();
    }
    @RequestMapping(value = "/command/query")
    public R liftCommandQuery(@RequestParam("wrkNo") Integer wrkNo) {
        Object o = redisUtil.get(RedisKeyType.LIFT.key + wrkNo);
        if (o == null) {
            return R.error();
        }
        LiftRedisCommand redisCommand = JSON.parseObject(o.toString(), LiftRedisCommand.class);
        return R.ok().add(redisCommand);
    }
    //回退命令
    @RequestMapping(value = "/command/rollback")
    public R liftCommandRollback(@RequestParam("wrkNo") Integer wrkNo
            , @RequestParam("commandStep") Integer commandStep) {
        Object o = redisUtil.get(RedisKeyType.LIFT.key + wrkNo);
        if (o == null) {
            return R.error();
        }
        LiftRedisCommand redisCommand = JSON.parseObject(o.toString(), LiftRedisCommand.class);
        redisCommand.setCommandStep(commandStep);
        redisUtil.set(RedisKeyType.LIFT.key + wrkNo, JSON.toJSONString(redisCommand));
        return R.ok();
    }
    //命令完成状态切换
    @RequestMapping(value = "/command/completeSwitch")
    public R liftCommandCompleteSwitch(@RequestParam("wrkNo") Integer wrkNo
            , @RequestParam("commandStep") Integer commandStep
            , @RequestParam("complete") Integer complete) {
        Object o = redisUtil.get(RedisKeyType.LIFT.key + wrkNo);
        if (o == null) {
            return R.error();
        }
        LiftRedisCommand redisCommand = JSON.parseObject(o.toString(), LiftRedisCommand.class);
        LiftAssignCommand assignCommand = redisCommand.getAssignCommand();
        List<ForkLiftCommand> commands = assignCommand.getCommands();
        ForkLiftCommand command = commands.get(commandStep);
        command.setComplete(complete != 0);
        redisUtil.set(RedisKeyType.LIFT.key + wrkNo, JSON.toJSONString(redisCommand));
        return R.ok();
    }
    //重启任务(命令)
    @RequestMapping(value = "/command/restart")
    public R liftCommandCompleteSwitch(@RequestParam("wrkNo") Integer wrkNo) {
        Object o = redisUtil.get(RedisKeyType.LIFT.key + wrkNo);
        if (o == null) {
            return R.error();
        }
        LiftRedisCommand redisCommand = JSON.parseObject(o.toString(), LiftRedisCommand.class);
        Short liftNo = redisCommand.getLiftNo();
        ForkLiftThread forkLiftThread = (ForkLiftThread) SlaveConnection.get(SlaveType.ForkLift, liftNo.intValue());
        if (forkLiftThread == null) {
            return R.error();
        }
        ForkLiftProtocol forkLiftProtocol = forkLiftThread.getStatus();
        if (forkLiftProtocol == null) {
            return R.error();
        }
        if (!forkLiftThread.isIdle()) {
            return R.error();
        }
        //提升机处于空闲状态,进行任务的恢复
        forkLiftThread.setSyncTaskNo(redisCommand.getWrkNo().intValue());//将提升机线程分配任务号
        return R.ok();
    }
    //删除任务(命令)
    @RequestMapping(value = "/command/del")
    public R liftCommandDel(@RequestParam("wrkNo") Integer wrkNo) {
        Object o = redisUtil.get(RedisKeyType.LIFT.key + wrkNo);
        if (o == null) {
            return R.error();
        }
        redisUtil.del(RedisKeyType.LIFT.key + wrkNo);
        return R.ok();
    }
}
src/main/java/com/zy/asrs/controller/LiftController.java
File was deleted
src/main/java/com/zy/asrs/controller/MonitorController.java
@@ -10,22 +10,12 @@
import com.zy.asrs.mapper.BasShuttleOptMapper;
import com.zy.asrs.mapper.ReportQueryMapper;
import com.zy.common.service.CommonService;
import com.zy.core.CrnThread;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.ShuttleProtocolStatusType;
import com.zy.core.enums.SlaveType;
import com.zy.core.model.LedSlave;
import com.zy.core.model.LiftSlave;
import com.zy.core.model.ShuttleSlave;
import com.zy.core.model.command.LedCommand;
import com.zy.core.model.protocol.CrnProtocol;
import com.zy.core.model.protocol.LiftProtocol;
import com.zy.core.model.protocol.NyShuttleProtocol;
import com.zy.core.properties.SlaveProperties;
import com.zy.core.thread.LedThread;
import com.zy.core.thread.LiftThread;
import com.zy.core.thread.NyShuttleThread;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -92,36 +82,6 @@
        Double yDistance = 0.0D;
        Double xDuration = 0.0D;
        Double yDuration = 0.0D;
        if (null != crnId) {
            CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crnId);
            if (crnThread != null) {
                CrnProtocol crnProtocol = crnThread.getCrnProtocol();
                if (crnProtocol != null) {
                    xSpeed = Double.valueOf(crnProtocol.getXSpeed());
                    ySpeed = Double.valueOf(crnProtocol.getYSpeed());
                    zSpeed = Double.valueOf(crnProtocol.getZSpeed());
                    switch (crnProtocol.getForkPos()) {
                        case 0:
                            forkPos = 1;
                            break;
                        case 1:
                            forkPos = 2;
                            break;
                        case 2:
                            forkPos = 0;
                            break;
                        default:
                            forkPos = 1;
                            break;
                    }
                    xDistance = Double.valueOf(crnProtocol.getXDistance());
                    yDistance = Double.valueOf(crnProtocol.getYDistance());
                    xDuration = Double.valueOf(crnProtocol.getXDuration());
                    yDuration = Double.valueOf(crnProtocol.getYDuration());
                }
            }
        }
        // 获取输送线plc线程
        LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, ledId);
@@ -303,83 +263,6 @@
            }
        }
        return R.ok().add(errorMsg);
    }
    /**
     * 设备异常通知
     */
    @GetMapping("/device/error")
    public R monitorDeviceError() {
        ArrayList<HashMap<String, Object>> list = new ArrayList<>();
        for (ShuttleSlave slave : slaveProperties.getShuttle()) {
            NyShuttleThread shuttleThread = (NyShuttleThread) SlaveConnection.get(SlaveType.Shuttle, slave.getId());
            NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
            if (shuttleProtocol == null) {
                continue;
            }
            HashMap<String, Object> map = new HashMap<>();
            if (shuttleProtocol.getProtocolStatusType().equals(ShuttleProtocolStatusType.OFFLINE)) {
                if (System.currentTimeMillis() - shuttleProtocol.getLastOnlineTime() > 1000 * 60 * 5) {
                    //离线超过五分钟
                    //设备离线中
                    map.put("deviceNo", shuttleProtocol.getShuttleNo());//设备号-小车号
                    map.put("errorMsg", "设备离线");//异常信息
                    map.put("device", "四向车");//异常信息
                    list.add(map);
                }
            }
            if (shuttleProtocol.getErrState() == 1) {
                //故障中
                map.put("deviceNo", shuttleProtocol.getShuttleNo());//设备号-小车号
                map.put("errorMsg", shuttleProtocol.getErrCode$());//异常信息
                map.put("device", "四向车");//异常信息
                list.add(map);
            }
        }
        for (LiftSlave slave : slaveProperties.getLift()) {
            LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, slave.getId());
            LiftProtocol liftProtocol = liftThread.getLiftProtocol();
            if (liftProtocol == null) {
                continue;
            }
            if (liftProtocol.getDeviceError()) {
                //故障中
                StringBuffer buffer = new StringBuffer();
                if (liftProtocol.getFrontOverrun()) {
                    buffer.append("前超限");
                }
                if (liftProtocol.getBackOverrun()) {
                    buffer.append("后超限");
                }
                if (liftProtocol.getLeftOverrun()) {
                    buffer.append("左超限");
                }
                if (liftProtocol.getRightOverrun()) {
                    buffer.append("右超限");
                }
                if (liftProtocol.getOverHeight()) {
                    buffer.append("超高");
                }
                if (liftProtocol.getOverWeight()) {
                    buffer.append("超重");
                }
                if (liftProtocol.getErrorCode() > 0) {
                    buffer.append(liftProtocol.getErrCode$());
                }
                HashMap<String, Object> map = new HashMap<>();
                map.put("deviceNo", liftProtocol.getLiftNo());//设备号-提升机号
                map.put("errorMsg", buffer.toString());//异常信息
                map.put("device", "提升机");//异常信息
                list.add(map);
            }
        }
        return R.ok().add(list);
    }
    /**
src/main/java/com/zy/asrs/controller/ShuttleController.java
@@ -3,11 +3,7 @@
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.core.annotations.ManagerAuth;
import com.core.common.BaseRes;
import com.core.common.Cools;
import com.core.common.R;
import com.core.exception.CoolException;
import com.zy.asrs.domain.param.ShuttleOperatorParam;
import com.zy.asrs.domain.vo.*;
import com.zy.asrs.entity.BasShuttle;
import com.zy.asrs.entity.WrkMast;
@@ -15,26 +11,19 @@
import com.zy.asrs.service.LocMastService;
import com.zy.asrs.service.WrkMastService;
import com.zy.asrs.utils.Utils;
import com.zy.common.model.NyShuttleOperaResult;
import com.zy.common.model.enums.NavigationMapType;
import com.zy.common.service.CommonService;
import com.zy.common.utils.NyHttpUtils;
import com.zy.common.utils.NyShuttleOperaUtils;
import com.zy.common.utils.RedisUtil;
import com.zy.common.utils.ShuttleDispatchUtils;
import com.zy.core.cache.MessageQueue;
import com.zy.core.cache.OutputQueue;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.dispatcher.ShuttleDispatchUtils;
import com.zy.core.enums.*;
import com.zy.core.model.ShuttleSlave;
import com.zy.core.model.Task;
import com.zy.core.model.command.NyShuttleHttpCommand;
import com.zy.core.model.command.ShuttleAssignCommand;
import com.zy.core.model.command.ShuttleCommand;
import com.zy.core.model.command.ShuttleRedisCommand;
import com.zy.core.model.protocol.NyShuttleProtocol;
import com.zy.core.model.param.ShuttleMoveLocParam;
import com.zy.core.model.protocol.ShuttleProtocol;
import com.zy.core.properties.SlaveProperties;
import com.zy.core.thread.NyShuttleThread;
import com.zy.core.thread.ShuttleThread;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@@ -76,11 +65,11 @@
            baseObj.put("shuttleNo", slave.getId());
            list.add(baseObj);
            // 获取四向穿梭车信息
            NyShuttleThread shuttleThread = (NyShuttleThread) SlaveConnection.get(SlaveType.Shuttle, slave.getId());
            ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, slave.getId());
            if (shuttleThread == null) {
                continue;
            }
            NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
            ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
            JSONObject shuttleData = JSON.parseObject(JSON.toJSONString(shuttleProtocol));
            if (shuttleProtocol == null || shuttleProtocol.getShuttleNo()==null) {
                if (shuttleData != null) {
@@ -101,8 +90,8 @@
            Integer chargeLine = basShuttleService.selectById(slave.getId()).getChargeLine();
            String lowerPower = "N";
            if (chargeLine != null && shuttleProtocol.getPowerPercent() != null) {
                lowerPower = shuttleProtocol.getPowerPercent() <= chargeLine ? "Y" : "N";
            if (chargeLine != null && shuttleProtocol.getBatteryPower() != null) {
                lowerPower = Integer.parseInt(shuttleProtocol.getBatteryPower()) <= chargeLine ? "Y" : "N";
            }
            shuttleData.put("lowerPower", lowerPower);//是否低电量
            baseObj.putAll(shuttleData);
@@ -124,7 +113,7 @@
            if (shuttleThread == null) {
                continue;
            }
            ShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
            ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
            if (shuttleProtocol == null) {
                continue;
            }
@@ -132,7 +121,7 @@
                continue;
            }
            vo.setWorkNo(shuttleProtocol.getTaskNo().intValue());//任务号
            vo.setWorkNo(shuttleProtocol.getTaskNo());//任务号
            if (shuttleProtocol.getTaskNo() > 0) {
                WrkMast wrkMast = wrkMastService.selectById(shuttleProtocol.getTaskNo());
                if (wrkMast != null) {
@@ -143,14 +132,6 @@
            if (shuttleProtocol.getProtocolStatusType() != null) {
                vo.setStatus(shuttleProtocol.getProtocolStatusType().desc);//状态
            }
            vo.setCodeOffsetX(shuttleProtocol.getCodeOffsetX());//读到的二维码X方向偏移量
            vo.setCodeOffsetY(shuttleProtocol.getCodeOffsetY());//读到的二维码Y方向偏移量
            vo.setCurrentVoltage(shuttleProtocol.getCurrentVoltage());//当前的电压值
            vo.setCurrentAnalogValue(shuttleProtocol.getCurrentAnalogValue());//当前的模拟量值
            vo.setCurrentMoveServoSpeed(shuttleProtocol.getCurrentMoveServoSpeed());//当前的行走伺服速度
            vo.setCurrentMoveServoLoad(shuttleProtocol.getCurrentMoveServoLoad() == null ? "" : shuttleProtocol.getCurrentMoveServoLoad() + "%");//当前的行走伺服负载率
            vo.setCurrentLiftServoLoad(shuttleProtocol.getCurrentLiftServoLoad() == null ? "" : shuttleProtocol.getCurrentLiftServoLoad() + "%");//当前的升降伺服负载率
            vo.setCurrentLiftServoSpeed(shuttleProtocol.getCurrentLiftServoSpeed());//当前的升降伺服速度
            vo.setPakMk(shuttleProtocol.getPakMk()?"Y" : "N");    // 作业标记
            vo.setLocNo(shuttleProtocol.getLocNo());//四向穿梭车当前库位号
            vo.setLev(shuttleProtocol.getLocNo() == null ? 0 : Utils.getLev(shuttleProtocol.getLocNo()));//四向穿梭车当前层高
@@ -217,8 +198,8 @@
        }
        ShuttleRedisCommand redisCommand = JSON.parseObject(o.toString(), ShuttleRedisCommand.class);
        ShuttleAssignCommand assignCommand = redisCommand.getAssignCommand();
        List<NyShuttleHttpCommand> commands = assignCommand.getCommands();
        NyShuttleHttpCommand command = commands.get(commandStep);
        List<ShuttleCommand> commands = assignCommand.getCommands();
        ShuttleCommand command = commands.get(commandStep);
        command.setComplete(complete != 0);
        redisUtil.set(RedisKeyType.SHUTTLE.key + wrkNo, JSON.toJSONString(redisCommand));
        return R.ok();
@@ -232,21 +213,17 @@
            return R.error();
        }
        ShuttleRedisCommand redisCommand = JSON.parseObject(o.toString(), ShuttleRedisCommand.class);
        Short shuttleNo = redisCommand.getShuttleNo();
        NyShuttleThread shuttleThread = (NyShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo.intValue());
        Integer shuttleNo = redisCommand.getShuttleNo();
        ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
        if (shuttleThread == null) {
            return R.error();
        }
        NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
        if (shuttleProtocol == null) {
            return R.error();
        }
        if (!shuttleProtocol.isIdle()) {
        if (!shuttleThread.isIdle()) {
            return R.error();
        }
        //四向穿梭车处于空闲状态,进行任务的恢复
        shuttleProtocol.setTaskNo(redisCommand.getWrkNo().intValue());//将四向穿梭车线程分配任务号
        shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.WORKING);//工作状态
        shuttleThread.setTaskNo(redisCommand.getWrkNo());//将四向穿梭车线程分配任务号
        shuttleThread.setProtocolStatus(ShuttleProtocolStatusType.WORKING);//工作状态
        return R.ok();
    }
@@ -265,133 +242,133 @@
    /************************** 手动操作 ******************************/
    /****************************************************************/
    @ManagerAuth(memo = "手动操作")
    @PostMapping("/operator/shuttle")
    public R shuttleOperator(ShuttleOperatorParam param){
        if (Cools.isEmpty(param.getShuttleNo(), param.getShuttleTaskMode())) {
            return R.parse(BaseRes.PARAM);
        }
        ShuttleAssignCommand assignCommand = new ShuttleAssignCommand();
        if (param.getShuttleTaskMode() == 1 || param.getShuttleTaskMode() == 2 || param.getShuttleTaskMode() == 14) {
            if (Cools.isEmpty(param.getSourceLocNo(), param.getDistLocNo())) {
                return R.parse(BaseRes.PARAM);
            }
            assignCommand.setSourceLocNo(param.getSourceLocNo());
            assignCommand.setLocNo(param.getDistLocNo());
        }
        for (ShuttleSlave shuttleSlave : slaveProperties.getShuttle()) {
            if (param.getShuttleNo().equals(shuttleSlave.getId())) {
                NyShuttleThread shuttleThread = (NyShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleSlave.getId());
                if (shuttleThread == null) {
                    throw new CoolException("四向穿梭车不在线");
                }
                NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
                if (shuttleProtocol == null) {
                    throw new CoolException("四向穿梭车不在线");
                }
                ShuttleTaskModeType shuttleTaskModeType = ShuttleTaskModeType.get(param.getShuttleTaskMode());
                assignCommand.setShuttleNo(shuttleSlave.getId().shortValue()); // 四向穿梭车编号
                assignCommand.setTaskMode(shuttleTaskModeType.id.shortValue());
                assignCommand.setTaskNo((short) commonService.getWorkNo(3));//获取任务号
                assignCommand.setAuto(false);//手动模式
                if (shuttleTaskModeType == ShuttleTaskModeType.TRANSPORT) {
                    //搬运货物任务
                    NyShuttleOperaResult result = NyShuttleOperaUtils.getShuttleTransportCommands(shuttleSlave.getId(), assignCommand.getTaskNo().intValue(), shuttleProtocol.getCurrentLocNo(), param.getSourceLocNo(), param.getDistLocNo());
                    if (result == null) {
                        throw new CoolException("路径计算失败");
                    }
                    assignCommand.setCommands(result.getCommands());
                    assignCommand.setNodes(result.getNodes());
                } else if (shuttleTaskModeType == ShuttleTaskModeType.MOVE_LOC_NO) {
                    //移动到目标库位
                    Integer mapType = NavigationMapType.NORMAL.id;
                    if (shuttleProtocol.getLiftPosition() == 2) {
                        mapType = NavigationMapType.DFX.id;
                    }
                    NyShuttleOperaResult result = NyShuttleOperaUtils.getStartToTargetCommands(shuttleSlave.getId(), assignCommand.getTaskNo().intValue(), shuttleProtocol.getCurrentLocNo(), param.getDistLocNo(), mapType);
                    if (result == null) {
                        throw new CoolException("路径计算失败");
                    }
                    assignCommand.setCommands(result.getCommands());
                    assignCommand.setNodes(result.getNodes());
                } else if (shuttleTaskModeType == ShuttleTaskModeType.PALLET_LIFT) {
                    //托盘顶升
                    NyShuttleHttpCommand command = NyHttpUtils.getPalletLiftCommand(shuttleSlave.getId(), assignCommand.getTaskNo().intValue(), true);
                    ArrayList<NyShuttleHttpCommand> commands = new ArrayList<>();
                    commands.add(command);
                    assignCommand.setCommands(commands);
                } else if (shuttleTaskModeType == ShuttleTaskModeType.PALLET_DOWN) {
                    //托盘下降
                    NyShuttleHttpCommand command = NyHttpUtils.getPalletLiftCommand(shuttleSlave.getId(), assignCommand.getTaskNo().intValue(), false);
                    ArrayList<NyShuttleHttpCommand> commands = new ArrayList<>();
                    commands.add(command);
                    assignCommand.setCommands(commands);
                } else if (shuttleTaskModeType == ShuttleTaskModeType.CHARGE) {
                    //充电开关
                    boolean charge = false;
                    if (shuttleProtocol.getChargState() == 1) {
                        //已充电,关闭充电
                        charge = false;
                    }else {
                        //开启充电
                        charge = true;
                    }
                    NyShuttleHttpCommand command = NyHttpUtils.getChargeCommand(shuttleSlave.getId(), assignCommand.getTaskNo().intValue(), charge);
                    ArrayList<NyShuttleHttpCommand> commands = new ArrayList<>();
                    commands.add(command);
                    assignCommand.setCommands(commands);
                } else if (shuttleTaskModeType == ShuttleTaskModeType.RESET) {
                    //复位
                    shuttleProtocol.setTaskNo(0);//工作号清空
                    shuttleProtocol.setToken(0);//令牌清空
                    shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.IDLE);//任务状态-空闲
                    shuttleProtocol.setPakMk(false);//作业标记复位
                    shuttleProtocol.setMoveLoc(false);
                    shuttleProtocol.setMoveType(0);
                    shuttleProtocol.setXStart(0);
                    shuttleProtocol.setXTarget(0);
                    shuttleProtocol.setXCurrent(0);
                    shuttleProtocol.setYStart(0);
                    shuttleProtocol.setYTarget(0);
                    shuttleProtocol.setYCurrent(0);
                    return R.ok();
                } else if (shuttleTaskModeType == ShuttleTaskModeType.SHUTTLE_CONTROL) {
                    //小车管制
                    NyShuttleHttpCommand suspendCommand = NyHttpUtils.getSuspendCommand(shuttleSlave.getId(), assignCommand.getTaskNo().intValue(), true);
                    ArrayList<NyShuttleHttpCommand> commands = new ArrayList<>();
                    commands.add(suspendCommand);
                    assignCommand.setCommands(commands);
                } else if (shuttleTaskModeType == ShuttleTaskModeType.SHUTTLE_CANCEL_CONTROL) {
                    //小车取消管制
                    NyShuttleHttpCommand suspendCommand = NyHttpUtils.getSuspendCommand(shuttleSlave.getId(), assignCommand.getTaskNo().intValue(), false);
                    ArrayList<NyShuttleHttpCommand> commands = new ArrayList<>();
                    commands.add(suspendCommand);
                    assignCommand.setCommands(commands);
                } else if (shuttleTaskModeType == ShuttleTaskModeType.MOVE_LOC_NO_WRK_MAST) {
                    //移动到目标库位(生成移动任务)
                    shuttleDispatchUtils.dispatchShuttle(commonService.getWorkNo(3), param.getDistLocNo(), param.getShuttleNo());
                    return R.ok();
                } else {
                    throw new CoolException("未知命令");
                }
                if (MessageQueue.offer(SlaveType.Shuttle, shuttleSlave.getId(), new Task(3, assignCommand))) {
                    return R.ok();
                } else {
                    throw new CoolException("命令下发失败");
                }
            }
        }
        return R.error();
    }
//    @ManagerAuth(memo = "手动操作")
//    @PostMapping("/operator/shuttle")
//    public R shuttleOperator(ShuttleOperatorParam param){
//        if (Cools.isEmpty(param.getShuttleNo(), param.getShuttleTaskMode())) {
//            return R.parse(BaseRes.PARAM);
//        }
//
//        ShuttleAssignCommand assignCommand = new ShuttleAssignCommand();
//
//        if (param.getShuttleTaskMode() == 1 || param.getShuttleTaskMode() == 2 || param.getShuttleTaskMode() == 14) {
//            if (Cools.isEmpty(param.getSourceLocNo(), param.getDistLocNo())) {
//                return R.parse(BaseRes.PARAM);
//            }
//            assignCommand.setSourceLocNo(param.getSourceLocNo());
//            assignCommand.setLocNo(param.getDistLocNo());
//        }
//
//        for (ShuttleSlave shuttleSlave : slaveProperties.getShuttle()) {
//            if (param.getShuttleNo().equals(shuttleSlave.getId())) {
//                ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleSlave.getId());
//                if (shuttleThread == null) {
//                    throw new CoolException("四向穿梭车不在线");
//                }
//                ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
//                if (shuttleProtocol == null) {
//                    throw new CoolException("四向穿梭车不在线");
//                }
//
//                ShuttleTaskModeType shuttleTaskModeType = ShuttleTaskModeType.get(param.getShuttleTaskMode().intValue());
//                assignCommand.setShuttleNo(shuttleSlave.getId()); // 四向穿梭车编号
//                assignCommand.setTaskMode(shuttleTaskModeType.id);
//                assignCommand.setTaskNo(commonService.getWorkNo(3));//获取任务号
//                assignCommand.setAuto(false);//手动模式
//
//                if (shuttleTaskModeType == ShuttleTaskModeType.TRANSPORT) {
//                    //搬运货物任务
//                    NyShuttleOperaResult result = NyShuttleOperaUtils.getShuttleTransportCommands(shuttleSlave.getId(), assignCommand.getTaskNo(), shuttleProtocol.getCurrentLocNo(), param.getSourceLocNo(), param.getDistLocNo());
//                    if (result == null) {
//                        throw new CoolException("路径计算失败");
//                    }
//
//                    assignCommand.setCommands(result.getCommands());
//                    assignCommand.setNodes(result.getNodes());
//                } else if (shuttleTaskModeType == ShuttleTaskModeType.MOVE_LOC_NO) {
//                    //移动到目标库位
//                    Integer mapType = NavigationMapType.NORMAL.id;
//                    if (shuttleProtocol.getLiftPosition() == 2) {
//                        mapType = NavigationMapType.DFX.id;
//                    }
//                    NyShuttleOperaResult result = NyShuttleOperaUtils.getStartToTargetCommands(shuttleSlave.getId(), assignCommand.getTaskNo().intValue(), shuttleProtocol.getCurrentLocNo(), param.getDistLocNo(), mapType);
//                    if (result == null) {
//                        throw new CoolException("路径计算失败");
//                    }
//
//                    assignCommand.setCommands(result.getCommands());
//                    assignCommand.setNodes(result.getNodes());
//                } else if (shuttleTaskModeType == ShuttleTaskModeType.PALLET_LIFT) {
//                    //托盘顶升
//                    NyShuttleHttpCommand command = NyHttpUtils.getPalletLiftCommand(shuttleSlave.getId(), assignCommand.getTaskNo().intValue(), true);
//                    ArrayList<NyShuttleHttpCommand> commands = new ArrayList<>();
//                    commands.add(command);
//                    assignCommand.setCommands(commands);
//                } else if (shuttleTaskModeType == ShuttleTaskModeType.PALLET_DOWN) {
//                    //托盘下降
//                    NyShuttleHttpCommand command = NyHttpUtils.getPalletLiftCommand(shuttleSlave.getId(), assignCommand.getTaskNo().intValue(), false);
//                    ArrayList<NyShuttleHttpCommand> commands = new ArrayList<>();
//                    commands.add(command);
//                    assignCommand.setCommands(commands);
//                } else if (shuttleTaskModeType == ShuttleTaskModeType.CHARGE) {
//                    //充电开关
//                    boolean charge = false;
//                    if (shuttleProtocol.getChargState() == 1) {
//                        //已充电,关闭充电
//                        charge = false;
//                    }else {
//                        //开启充电
//                        charge = true;
//                    }
//                    NyShuttleHttpCommand command = NyHttpUtils.getChargeCommand(shuttleSlave.getId(), assignCommand.getTaskNo().intValue(), charge);
//                    ArrayList<NyShuttleHttpCommand> commands = new ArrayList<>();
//                    commands.add(command);
//                    assignCommand.setCommands(commands);
//                } else if (shuttleTaskModeType == ShuttleTaskModeType.RESET) {
//                    //复位
//                    shuttleProtocol.setTaskNo(0);//工作号清空
//                    shuttleProtocol.setToken(0);//令牌清空
//                    shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.IDLE);//任务状态-空闲
//                    shuttleProtocol.setPakMk(false);//作业标记复位
//
//                    shuttleProtocol.setMoveLoc(false);
//                    shuttleProtocol.setMoveType(0);
//                    shuttleProtocol.setXStart(0);
//                    shuttleProtocol.setXTarget(0);
//                    shuttleProtocol.setXCurrent(0);
//                    shuttleProtocol.setYStart(0);
//                    shuttleProtocol.setYTarget(0);
//                    shuttleProtocol.setYCurrent(0);
//                    return R.ok();
//                } else if (shuttleTaskModeType == ShuttleTaskModeType.SHUTTLE_CONTROL) {
//                    //小车管制
//                    NyShuttleHttpCommand suspendCommand = NyHttpUtils.getSuspendCommand(shuttleSlave.getId(), assignCommand.getTaskNo().intValue(), true);
//                    ArrayList<NyShuttleHttpCommand> commands = new ArrayList<>();
//                    commands.add(suspendCommand);
//                    assignCommand.setCommands(commands);
//                } else if (shuttleTaskModeType == ShuttleTaskModeType.SHUTTLE_CANCEL_CONTROL) {
//                    //小车取消管制
//                    NyShuttleHttpCommand suspendCommand = NyHttpUtils.getSuspendCommand(shuttleSlave.getId(), assignCommand.getTaskNo().intValue(), false);
//                    ArrayList<NyShuttleHttpCommand> commands = new ArrayList<>();
//                    commands.add(suspendCommand);
//                    assignCommand.setCommands(commands);
//                } else if (shuttleTaskModeType == ShuttleTaskModeType.MOVE_LOC_NO_WRK_MAST) {
//                    //移动到目标库位(生成移动任务)
//                    shuttleDispatchUtils.dispatchShuttle(commonService.getWorkNo(3), param.getDistLocNo(), param.getShuttleNo());
//                    return R.ok();
//                } else {
//                    throw new CoolException("未知命令");
//                }
//
//                if (MessageQueue.offer(SlaveType.Shuttle, shuttleSlave.getId(), new Task(3, assignCommand))) {
//                    return R.ok();
//                } else {
//                    throw new CoolException("命令下发失败");
//                }
//            }
//        }
//        return R.error();
//    }
    @PostMapping("/detl/update")
    @ManagerAuth(memo = "修改数据")
@@ -399,22 +376,15 @@
                           @RequestParam Integer workNo,
                           @RequestParam String pakMk,
                           @RequestParam Integer token) {
        NyShuttleThread shuttleThread = (NyShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
        ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
        if (shuttleThread == null) {
            return R.error("plc已掉线");
        }
        NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
        if (shuttleProtocol == null) {
            return R.error("plc已掉线");
        }
        if (workNo != null) {
            shuttleProtocol.setTaskNo(workNo);
            shuttleThread.setTaskNo(workNo);
        }
        if (pakMk != null) {
            shuttleProtocol.setPakMk(pakMk.equals("Y"));
        }
        if (token != null) {
            shuttleProtocol.setToken(token);
            shuttleThread.setPakMk(pakMk.equals("Y"));
        }
        return R.ok();
    }
@@ -426,7 +396,7 @@
        if (basShuttle == null) {
            return R.error("四向穿梭车不存在");
        }
//        basShuttle.setRunSpeed(runSpeed);
        basShuttle.setRunSpeed(runSpeed);
        basShuttle.setChargeLine(chargeLine);
        if (!basShuttleService.updateById(basShuttle)) {
            return R.error();
@@ -445,28 +415,29 @@
                     @RequestParam Integer xTarget,
                     @RequestParam Integer yStart,
                     @RequestParam Integer yTarget) {
        NyShuttleThread shuttleThread = (NyShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
        ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
        if (shuttleThread == null) {
            return R.error();
        }
        NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
        ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
        if (shuttleProtocol == null) {
            return R.error();
        }
        if (!shuttleProtocol.isIdle()) {
        if (!shuttleThread.isIdle()) {
            return R.error("小车忙碌中");
        }
        shuttleProtocol.setMoveLoc(true);//开启跑库
        shuttleProtocol.setMoveType(moveType);
        shuttleProtocol.setXStart(xStart);
        shuttleProtocol.setXTarget(xTarget);
        shuttleProtocol.setXCurrent(xStart);
        shuttleProtocol.setYStart(yStart);
        shuttleProtocol.setYTarget(yTarget);
        shuttleProtocol.setYCurrent(yStart);
        ShuttleMoveLocParam param = new ShuttleMoveLocParam();
        param.setShuttleNo(shuttleNo);
        param.setMoveType(moveType);
        param.setStartX(xStart);
        param.setTargetX(xTarget);
        param.setStartY(yStart);
        param.setTargetY(yTarget);
        shuttleThread.enableMoveLoc(param, true);
        return R.ok();
    }
src/main/java/com/zy/asrs/controller/SiteController.java
@@ -2,33 +2,20 @@
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.annotations.ManagerAuth;
import com.core.common.Cools;
import com.core.common.R;
import com.zy.asrs.domain.vo.PlcErrorTableVo;
import com.zy.asrs.domain.vo.SiteTableVo;
import com.zy.asrs.entity.BasDevp;
import com.zy.asrs.entity.BasSte;
import com.zy.asrs.entity.WrkCharge;
import com.zy.asrs.service.BasDevpService;
import com.zy.asrs.service.BasSteService;
import com.zy.asrs.service.WrkChargeService;
import com.zy.common.model.enums.WrkChargeType;
import com.zy.common.service.CommonService;
import com.zy.core.DevpThread;
import com.zy.core.News;
import com.zy.core.cache.MessageQueue;
import com.zy.core.cache.OutputQueue;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.SlaveType;
import com.zy.core.enums.SteChargeType;
import com.zy.core.enums.SteStatusType;
import com.zy.core.model.DevpSlave;
import com.zy.core.model.Task;
import com.zy.core.model.protocol.StaProtocol;
import com.zy.core.model.protocol.SteProtocol;
import com.zy.core.properties.SlaveProperties;
import com.zy.core.thread.SiemensDevpThread;
import com.zy.core.thread.SteThread;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -37,7 +24,6 @@
/**
 * 输送设备接口
 * Created by vincent on 2020-06-01
 */
@Slf4j
@RestController
@@ -48,32 +34,6 @@
    private SlaveProperties slaveProperties;
    @Autowired
    private BasDevpService basDevpService;
    @Autowired
    private WrkChargeService wrkChargeService;
    @Autowired
    private BasSteService basSteService;
    @Autowired
    private CommonService commonService;
    @GetMapping("/io/mode/info/site")
    @ManagerAuth(memo = "充电模式")
    public R ioMode(){
        List<Map<String, Object>> res = new ArrayList<>();
        for (DevpSlave devp : slaveProperties.getDevp()) {
            SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
            Map<String, Object> map1 = new HashMap<>();
            map1.put("floor", 1);
            map1.put("modeVal", !devpThread.charge0);
            map1.put("modeDesc", !devpThread.charge0?"充电中":"关闭");
            res.add(map1);
            Map<String, Object> map2 = new HashMap<>();
            map2.put("floor", 2);
            map2.put("modeVal", devpThread.charge1);
            map2.put("modeDesc", devpThread.charge1?"充电中":"关闭");
            res.add(map2);
        }
        return R.ok().add(res);
    }
    @PostMapping("/table/site")
    @ManagerAuth(memo = "站点信息表")
@@ -136,14 +96,6 @@
            for(Map.Entry<Integer, StaProtocol> entry : station.entrySet()) {
                StaProtocol staProtocol = entry.getValue();
//                if (staProtocol) {
//                    PlcErrorTableVo vo = new PlcErrorTableVo();
//                    vo.setNo(entry.getKey());   //  序号
//
//                    vo.setPlcDesc("");  //  todo:luxiaotao plc错误描述
//                    vo.setError("");    //  todo:luxiaotao 异常信息
//                    list.add(vo);
//                }
            }
        }
@@ -156,7 +108,6 @@
            }else{
                return -1;
            }
        });
        return R.ok().add(list);
    }
src/main/java/com/zy/asrs/domain/enums/CrnStatusType.java
File was deleted
src/main/java/com/zy/asrs/domain/param/CrnDemoParam.java
File was deleted
src/main/java/com/zy/asrs/domain/param/CrnOperatorParam.java
File was deleted
src/main/java/com/zy/asrs/domain/param/SteModeParam.java
File was deleted
src/main/java/com/zy/asrs/domain/param/SteOperatorParam.java
File was deleted
src/main/java/com/zy/asrs/domain/vo/CommandLogVo.java
File was deleted
src/main/java/com/zy/asrs/domain/vo/CrnDetailVo.java
File was deleted
src/main/java/com/zy/asrs/domain/vo/CrnLatestDataVo.java
File was deleted
src/main/java/com/zy/asrs/domain/vo/CrnMsgTableVo.java
File was deleted
src/main/java/com/zy/asrs/domain/vo/CrnStateTableVo.java
File was deleted
src/main/java/com/zy/asrs/domain/vo/LiftStateTableVo.java
@@ -1,7 +1,6 @@
package com.zy.asrs.domain.vo;
import com.zy.core.enums.LiftNotReadyType;
import com.zy.core.enums.LiftProtocolStatusType;
import com.zy.core.enums.ForkLiftProtocolStatusType;
import lombok.Data;
@Data
@@ -159,9 +158,9 @@
    public String getProtocolStatus$() {
        if (this.protocolStatus == null) {
            return LiftProtocolStatusType.OFFLINE.desc;
            return ForkLiftProtocolStatusType.NONE.desc;
        }
        return LiftProtocolStatusType.get(this.protocolStatus).desc;
        return ForkLiftProtocolStatusType.get(this.protocolStatus).desc;
    }
}
src/main/java/com/zy/asrs/domain/vo/ShuttleMsgTableVo.java
@@ -27,46 +27,6 @@
    private String pakMk = "-";
    /**
     * 读到的二维码X方向偏移量
     */
    private Short codeOffsetX;
    /**
     * 读到的二维码Y方向偏移量
     */
    private Short codeOffsetY;
    /**
     * 当前的电压值
     */
    private Integer currentVoltage;
    /**
     * 当前的模拟量值
     */
    private Short currentAnalogValue;
    /**
     * 当前的升降伺服速度
     */
    private Short currentLiftServoSpeed;
    /**
     * 当前的行走伺服速度
     */
    private Short currentMoveServoSpeed;
    /**
     * 当前的升降伺服负载率
     */
    private String currentLiftServoLoad;
    /**
     * 当前的行走伺服负载率
     */
    private String currentMoveServoLoad;
    /**
     * 四向穿梭车库位号
     */
    private String locNo;
src/main/java/com/zy/asrs/domain/vo/ShuttleStateTableVo.java
@@ -1,9 +1,5 @@
package com.zy.asrs.domain.vo;
import com.core.common.SpringUtils;
import com.zy.asrs.entity.BasShuttleErr;
import com.zy.asrs.service.BasShuttleErrService;
import com.zy.core.enums.ShuttleErrorCodeType;
import com.zy.core.enums.ShuttleProtocolStatusType;
import com.zy.core.enums.ShuttleStatusType;
import lombok.Data;
@@ -102,11 +98,6 @@
    private String statusErrorCode;
    /**
     * 错误信息码枚举
     */
    private ShuttleErrorCodeType errorCodeType;
    /**
     * PLC输入状态
     */
    private Short plcInputStatus;
@@ -165,21 +156,6 @@
     * 当前位置
     */
    public String loca = "-";
    public String getErrorCode$() {
        if(this.errorCodeType == null) return null;
        return this.errorCodeType.desc;
    }
    public void setErrorCode(Short errorCode) {
        this.errorCode = ShuttleErrorCodeType.get(errorCode.intValue()).desc;
        this.errorCodeType = ShuttleErrorCodeType.get(errorCode.intValue());
    }
    public void setErrorCode(ShuttleErrorCodeType type) {
        this.errorCode = type.desc;
        this.errorCodeType = type;
    }
    public String getPlcOutputLift$() {
        if (this.plcOutputLift == null) {
src/main/java/com/zy/asrs/domain/vo/SteMsgTableVo.java
File was deleted
src/main/java/com/zy/asrs/domain/vo/SteSensorDataVo.java
File was deleted
src/main/java/com/zy/asrs/domain/vo/SteStateTableVo.java
File was deleted
src/main/java/com/zy/asrs/entity/BasCrnError.java
File was deleted
src/main/java/com/zy/asrs/entity/BasCrnOpt.java
File was deleted
src/main/java/com/zy/asrs/entity/BasCrnp.java
File was deleted
src/main/java/com/zy/asrs/entity/BasErrLog.java
File was deleted
src/main/java/com/zy/asrs/entity/BasLift.java
@@ -1,13 +1,11 @@
package com.zy.asrs.entity;
import com.alibaba.fastjson.JSON;
import com.core.common.Cools;import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.enums.IdType;
import com.baomidou.mybatisplus.annotations.TableField;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.zy.core.model.protocol.NyShuttleProtocol;
import org.springframework.format.annotation.DateTimeFormat;
import com.core.common.SpringUtils;
import com.zy.system.service.UserService;
@@ -115,13 +113,6 @@
            return String.valueOf(user.getUsername());
        }
        return null;
    }
    public NyShuttleProtocol.NyShuttlePointClass getPoint$() {
        if (Cools.isEmpty(this.point)){
            return null;
        }
        return JSON.parseObject(this.point, NyShuttleProtocol.NyShuttlePointClass.class);
    }
}
src/main/java/com/zy/asrs/entity/BasShuttle.java
@@ -106,13 +106,6 @@
    private String memo;
    /**
     * 提升机号
     */
    @ApiModelProperty(value= "提升机号")
    @TableField("lift_no")
    private Integer liftNo;
    /**
     * 作业标记
     */
    @ApiModelProperty(value= "作业标记")
@@ -133,9 +126,16 @@
    @TableField("device_status")
    private String deviceStatus;
    /**
     * 小车禁用楼层
     */
    @ApiModelProperty(value= "小车禁用楼层")
    @TableField("disable_lev")
    private String disableLev;
    public BasShuttle() {}
    public BasShuttle(Integer shuttleNo, Integer status, Integer shuttleStatus, Integer wrkNo, String idleLoc, Integer autoCharge, Integer chargeLine, Long createBy, Date createTime, Long updateBy, Date updateTime, String memo, Integer liftNo, Boolean pakMk, String deviceStatus) {
    public BasShuttle(Integer shuttleNo, Integer status, Integer shuttleStatus, Integer wrkNo, String idleLoc, Integer autoCharge, Integer chargeLine, Long createBy, Date createTime, Long updateBy, Date updateTime, String memo, Boolean pakMk, String deviceStatus) {
        this.shuttleNo = shuttleNo;
        this.status = status;
        this.shuttleStatus = shuttleStatus;
@@ -148,7 +148,6 @@
        this.updateBy = updateBy;
        this.updateTime = updateTime;
        this.memo = memo;
        this.liftNo = liftNo;
        this.pakMk = pakMk;
        this.deviceStatus = deviceStatus;
    }
src/main/java/com/zy/asrs/entity/BasSte.java
File was deleted
src/main/java/com/zy/asrs/entity/BasSteErr.java
File was deleted
src/main/java/com/zy/asrs/entity/BasSteErrLog.java
File was deleted
src/main/java/com/zy/asrs/entity/BasSteOpt.java
File was deleted
src/main/java/com/zy/asrs/entity/LocMast.java
@@ -29,35 +29,9 @@
    @TableField("loc_no")
    private String locNo;
    /**
     * 库位类型
     */
    @ApiModelProperty(value= "库位类型")
    @TableField("whs_type")
    private Long whsType;
    @ApiModelProperty(value= "")
    @TableField("plt_type")
    private Integer pltType;
    @ApiModelProperty(value= "")
    @TableField("ctn_type")
    private Integer ctnType;
    @ApiModelProperty(value= "库位状态")
    @TableField("loc_sts")
    private String locSts;
    @ApiModelProperty(value= "")
    @TableField("sheet_no")
    private String sheetNo;
    /**
     * 堆垛机号(asr_bas_crnp)
     */
    @ApiModelProperty(value= "堆垛机号")
    @TableField("crn_no")
    private Integer crnNo;
    /**
     * 排
@@ -77,13 +51,6 @@
    @ApiModelProperty(value= "层")
    private Integer lev1;
    /**
     * 满板
     */
    @ApiModelProperty(value= "满板")
    @TableField("full_plt")
    private String fullPlt;
    @ApiModelProperty(value= "")
    @TableField("loc_type")
    private String locType;
@@ -101,16 +68,8 @@
    private Short locType3;
    @ApiModelProperty(value= "")
    @TableField("out_enable")
    private String outEnable;
    @ApiModelProperty(value= "")
    @TableField("io_time")
    private Date ioTime;
    @ApiModelProperty(value= "")
    @TableField("first_time")
    private Date firstTime;
    /**
     * 修改人员
@@ -149,30 +108,7 @@
    private String errorMemo;
    @ApiModelProperty(value= "")
    @TableField("ctn_kind")
    private Integer ctnKind;
    @ApiModelProperty(value= "")
    @TableField("sc_weight")
    private Double scWeight;
    @ApiModelProperty(value= "")
    @TableField("inv_wh")
    private String invWh;
    @ApiModelProperty(value= "")
    private String mk;
    @ApiModelProperty(value= "")
    private String barcode;
    @ApiModelProperty(value= "")
    @TableField("Pdc_type")
    private String PdcType;
    @ApiModelProperty(value= "")
    @TableField("ctn_no")
    private String ctnNo;
    @ApiModelProperty(value= "库位真实二维码")
    @TableField("qr_code_value")
@@ -183,13 +119,6 @@
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.ioTime);
    }
    public String getFirstTime$(){
        if (Cools.isEmpty(this.firstTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.firstTime);
    }
    public String getLocType1$() {
src/main/java/com/zy/asrs/entity/StaDesc.java
@@ -6,7 +6,6 @@
import com.baomidou.mybatisplus.enums.IdType;
import com.core.common.Cools;
import com.core.common.SpringUtils;
import com.zy.asrs.service.BasCrnpService;
import com.zy.asrs.service.BasDevpService;
import com.zy.system.entity.User;
import com.zy.system.service.UserService;
@@ -183,15 +182,6 @@
    public Integer getCrnNo() {
        return crnNo;
    }
    public String getCrnNo$(){
        BasCrnpService service = SpringUtils.getBean(BasCrnpService.class);
        BasCrnp basCrnp = service.selectById(this.crnNo);
        if (!Cools.isEmpty(basCrnp)){
            return String.valueOf(basCrnp.getCrnNo());
        }
        return null;
    }
    public void setCrnNo(Integer crnNo) {
src/main/java/com/zy/asrs/entity/WrkCharge.java
File was deleted
src/main/java/com/zy/asrs/entity/WrkMast.java
@@ -34,18 +34,7 @@
    private Integer wrkNo;
    @ApiModelProperty(value= "")
    @TableField("inv_wh")
    private String invWh;
    @ApiModelProperty(value= "")
    private Date ymd;
    @ApiModelProperty(value= "")
    private String mk;
    @ApiModelProperty(value= "")
    @TableField("whs_type")
    private Integer whsType;
    /**
     * 工作状态
@@ -60,31 +49,6 @@
    @ApiModelProperty(value= "入出库类型")
    @TableField("io_type")
    private Integer ioType;
    /**
     * 堆垛机
     */
    @ApiModelProperty(value= "堆垛机")
    @TableField("crn_no")
    private Integer crnNo;
    /**
     * 穿梭车
     */
    @ApiModelProperty(value= "穿梭车")
    @TableField("ste_no")
    private Integer steNo;
    /**
     * 边缘库位
     */
    @ApiModelProperty(value= "边缘库位")
    @TableField("out_most")
    private Integer outMost;
    @ApiModelProperty(value= "")
    @TableField("sheet_no")
    private String sheetNo;
    /**
     * 优先级
@@ -125,112 +89,12 @@
    @TableField("source_loc_no")
    private String sourceLocNo;
    @ApiModelProperty(value= "")
    @TableField("loc_sts")
    private String locSts;
    /**
     * 拣料
     */
    @ApiModelProperty(value= "拣料")
    private String picking;
    @ApiModelProperty(value= "")
    @TableField("link_mis")
    private String linkMis;
    @ApiModelProperty(value= "")
    @TableField("online_yn")
    private String onlineYn;
    @ApiModelProperty(value= "")
    @TableField("upd_mk")
    private String updMk;
    /**
     * 退出
     */
    @ApiModelProperty(value= "退出")
    @TableField("exit_mk")
    private String exitMk;
    @ApiModelProperty(value= "")
    @TableField("plt_type")
    private Integer pltType;
    /**
     * 空板
     */
    @ApiModelProperty(value= "空板")
    @TableField("empty_mk")
    private String emptyMk;
    /**
     * 工作时间
     */
    @ApiModelProperty(value= "工作时间")
    @TableField("io_time")
    private Date ioTime;
    @ApiModelProperty(value= "")
    @TableField("ctn_type")
    private Integer ctnType;
    @ApiModelProperty(value= "")
    private String packed;
    @ApiModelProperty(value= "")
    @TableField("ove_mk")
    private String oveMk;
    @ApiModelProperty(value= "")
    @TableField("mtn_type")
    private Double mtnType;
    @ApiModelProperty(value= "")
    @TableField("user_no")
    private String userNo;
    /**
     * 堆垛机启动时间
     */
    @ApiModelProperty(value= "堆垛机启动时间")
    @TableField("crn_str_time")
    private Date crnStrTime;
    /**
     * 堆垛机停止时间
     */
    @ApiModelProperty(value= "堆垛机停止时间")
    @TableField("crn_end_time")
    private Date crnEndTime;
    @ApiModelProperty(value= "")
    @TableField("plc_str_time")
    private Date plcStrTime;
    @ApiModelProperty(value= "")
    @TableField("crn_pos_time")
    private Date crnPosTime;
    @ApiModelProperty(value= "")
    @TableField("load_time")
    private Double loadTime;
    @ApiModelProperty(value= "")
    @TableField("exp_time")
    private Double expTime;
    @ApiModelProperty(value= "")
    @TableField("ref_wrkno")
    private Double refWrkno;
    /**
     * 拣料时间
     */
    @ApiModelProperty(value= "拣料时间")
    @TableField("ref_iotime")
    private Date refIotime;
    /**
     * 修改人员
@@ -261,10 +125,6 @@
    private Date appeTime;
    @ApiModelProperty(value= "")
    @TableField("pause_mk")
    private String pauseMk;
    @ApiModelProperty(value= "")
    @TableField("error_time")
    private Date errorTime;
@@ -272,56 +132,17 @@
    @TableField("error_memo")
    private String errorMemo;
    @ApiModelProperty(value= "")
    @TableField("ctn_kind")
    private Integer ctnKind;
    @ApiModelProperty(value= "")
    @TableField("manu_type")
    private String manuType;
    /**
     * 备注
     */
    @ApiModelProperty(value= "备注")
    private String memo;
    @ApiModelProperty(value= "")
    @TableField("sc_weight")
    private Double scWeight;
    @ApiModelProperty(value= "")
    @TableField("log_mk")
    private String logMk;
    @ApiModelProperty(value= "")
    @TableField("log_err_time")
    private Date logErrTime;
    @ApiModelProperty(value= "")
    @TableField("log_err_memo")
    private String logErrMemo;
    /**
     * 条码
     */
    @ApiModelProperty(value= "条码")
    private String barcode;
    @ApiModelProperty(value= "")
    @TableField("Pdc_type")
    private String pdcType;
    @ApiModelProperty(value= "")
    @TableField("ctn_no")
    private String ctnNo;
    /**
     * 满板
     */
    @ApiModelProperty(value= "满板")
    @TableField("full_plt")
    private String fullPlt;
    /**
     * 四向穿梭车号
@@ -351,22 +172,6 @@
        BasWrkIotype entity = mapper.selectById(this.ioType);
        if (entity != null) {
            return entity.getIoDesc();
        }
        return null;
    }
    public String getYmd$(){
        if (Cools.isEmpty(this.ymd)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.ymd);
    }
    public String getCrnNo$(){
        BasCrnpService service = SpringUtils.getBean(BasCrnpService.class);
        BasCrnp basCrnp = service.selectById(this.crnNo);
        if (!Cools.isEmpty(basCrnp)){
            return String.valueOf(basCrnp.getCrnNo());
        }
        return null;
    }
@@ -421,41 +226,6 @@
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.ioTime);
    }
    public String getCrnStrTime$(){
        if (Cools.isEmpty(this.crnStrTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.crnStrTime);
    }
    public String getCrnEndTime$(){
        if (Cools.isEmpty(this.crnEndTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.crnEndTime);
    }
    public String getPlcStrTime$(){
        if (Cools.isEmpty(this.plcStrTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.plcStrTime);
    }
    public String getCrnPosTime$(){
        if (Cools.isEmpty(this.crnPosTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.crnPosTime);
    }
    public String getRefIotime$(){
        if (Cools.isEmpty(this.refIotime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.refIotime);
    }
    public String getModiUser$(){
        UserService service = SpringUtils.getBean(UserService.class);
        User user = service.selectById(this.modiUser);
@@ -504,25 +274,6 @@
            errorMemo = errorMemo.substring(0, 150);
        }
        this.errorMemo = errorMemo;
    }
    public String getLogErrTime$(){
        if (Cools.isEmpty(this.logErrTime)){
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.logErrTime);
    }
    public String getOutMost$() {
        if (null == this.outMost){ return null; }
        switch (this.outMost){
            case 1:
                return "边缘库位";
            case 0:
                return "内联库位";
            default:
                return String.valueOf(this.outMost);
        }
    }
}
src/main/java/com/zy/asrs/entity/WrkMastLog.java
@@ -6,7 +6,6 @@
import com.baomidou.mybatisplus.enums.IdType;
import com.core.common.Cools;
import com.core.common.SpringUtils;
import com.zy.asrs.service.BasCrnpService;
import com.zy.asrs.service.BasDevpService;
import com.zy.asrs.service.LocMastService;
import com.zy.asrs.service.WrkMastService;
@@ -357,15 +356,6 @@
            return "";
        }
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.ymd);
    }
    public String getCrnNo$(){
        BasCrnpService service = SpringUtils.getBean(BasCrnpService.class);
        BasCrnp basCrnp = service.selectById(this.crnNo);
        if (!Cools.isEmpty(basCrnp)){
            return String.valueOf(basCrnp.getCrnNo());
        }
        return null;
    }
    public String getWrkDate$(){
src/main/java/com/zy/asrs/mapper/BasCrnErrorMapper.java
File was deleted
src/main/java/com/zy/asrs/mapper/BasCrnOptMapper.java
File was deleted
src/main/java/com/zy/asrs/mapper/BasCrnpMapper.java
File was deleted
src/main/java/com/zy/asrs/mapper/BasErrLogMapper.java
File was deleted
src/main/java/com/zy/asrs/mapper/BasSteErrLogMapper.java
File was deleted
src/main/java/com/zy/asrs/mapper/BasSteErrMapper.java
File was deleted
src/main/java/com/zy/asrs/mapper/BasSteMapper.java
File was deleted
src/main/java/com/zy/asrs/mapper/BasSteOptMapper.java
File was deleted
src/main/java/com/zy/asrs/mapper/LocMastMapper.java
@@ -4,7 +4,6 @@
import com.zy.asrs.entity.LocMast;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import java.util.List;
@@ -12,27 +11,6 @@
@Mapper
@Repository
public interface LocMastMapper extends BaseMapper<LocMast> {
    @Select("select distinct row1 from asr_loc_mast where crn_no = #{crnNo} and row1 > 30")
    List<Integer> queryDistinctRow(@Param("crnNo")Integer crnNo);
    LocMast queryFreeLocMast(@Param("row") Integer row, @Param("locType1") Short locType1);
    @Select("select loc_no from asr_loc_mast where 1=1 and loc_sts = 'O' and crn_no = #{crnNo}")
    List<String> queryGroupEmptyStock(Integer crnNo);
    @Select("select top 1 bay1 from asr_loc_mast order by bay1 desc")
    Short selectTotalBay();
    LocMast queryDemoSourceLoc(@Param("crnNo") Integer crnNo);
    LocMast queryDemoLoc(@Param("crnNo") Integer crnNo);
    @Select("select count(*) as count from asr_loc_mast where 1=1 and loc_sts = 'O' and loc_type1 = #{locType1} and crn_no = #{crnNo}")
    Integer selectEmptyLocCount(@Param("locType1") Short locType1, @Param("crnNo") Integer crnNo);
    @Select("select loc_no from asr_loc_mast where crn_no = #{crnNo} and loc_sts='O' order by lev1, bay1, row1")
    List<String> getDemoNextLoc(Integer crnNo);
    LocMast queryByLoc(String locNo);
src/main/java/com/zy/asrs/mapper/WrkChargeMapper.java
File was deleted
src/main/java/com/zy/asrs/mapper/WrkMastMapper.java
@@ -11,11 +11,6 @@
@Repository
public interface WrkMastMapper extends BaseMapper<WrkMast> {
//    @Select("select * from asr_wrk_mast where ((wrk_sts = 4 Or wrk_sts = 14 ) and io_type <> 103 and io_type <> 104 and io_type <> 107 ) or (wrk_sts = 2 and io_type=6) order by upd_mk,io_time,wrk_no")
    List<WrkMast> selectToBeCompleteData();
    List<WrkMast> selectToBeHistoryData();
    // wcs ---------------------------------------------
    // 入库第一步,扫码仪获取条码信息时查询
//    @Select("select top 1 * from asr_wrk_mast where source_sta_no=#{sourceStaNo} and wrk_sts=2 and barcode=#{barcode} and (io_type=1 or io_type=10) order by io_pri desc,io_time,wrk_no ASC")
@@ -56,4 +51,6 @@
    List<WrkMast> selectInWrkMastByLiftNo(Integer liftNo);//搜索指定提升机的入库任务
    WrkMast selectChargeWorking(Integer shuttleNo);
}
src/main/java/com/zy/asrs/service/BasCrnOptService.java
File was deleted
src/main/java/com/zy/asrs/service/BasCrnpService.java
File was deleted
src/main/java/com/zy/asrs/service/BasErrLogService.java
File was deleted
src/main/java/com/zy/asrs/service/BasSteErrLogService.java
File was deleted
src/main/java/com/zy/asrs/service/BasSteErrService.java
File was deleted
src/main/java/com/zy/asrs/service/BasSteOptService.java
File was deleted
src/main/java/com/zy/asrs/service/BasSteService.java
File was deleted
src/main/java/com/zy/asrs/service/WrkChargeService.java
File was deleted
src/main/java/com/zy/asrs/service/WrkMastService.java
@@ -1,18 +1,15 @@
package com.zy.asrs.service;
import com.baomidou.mybatisplus.service.IService;
import com.zy.asrs.entity.LocMast;
import com.zy.asrs.entity.WrkMast;
import java.util.List;
public interface WrkMastService extends IService<WrkMast> {
    int getWorkingMast(Integer devpNo);
    WrkMast selectByWorkNo(Integer workNo);
    List<WrkMast> selectToBeCompleteData();
    List<WrkMast> selectToBeHistoryData();
    Boolean judgeInbound(WrkMast wrkMast);
    //查询指定楼层待分配车辆的任务
    List<WrkMast> selectNoShuttleWrkByLev(Integer lev);
@@ -23,4 +20,16 @@
    //查询指定楼层已分配车辆的出库任务
    List<WrkMast> selectShuttleOutWrkByLev(Integer lev);
    WrkMast selectChargeWorking(Integer shuttleNo);
    Boolean hasBusyByShuttle(Integer shuttleNo);
    WrkMast selectShuttleHasMoveWorking(Integer shuttleNo);
    WrkMast selectShuttleWorking(Integer shuttleNo);//是否有穿梭车任务(移库任务除外)
    List<WrkMast> selectShuttleMoveWrk();
    WrkMast selectLiftWrkMast(Integer liftNo);
}
src/main/java/com/zy/asrs/service/impl/BasCrnOptServiceImpl.java
File was deleted
src/main/java/com/zy/asrs/service/impl/BasCrnpServiceImpl.java
File was deleted
src/main/java/com/zy/asrs/service/impl/BasDevpServiceImpl.java
@@ -58,9 +58,6 @@
            if(station.getWrkNo()!=null && station.getWrkNo()>0) {
                throw new CoolException(devpNo+"站点已有工作号");
            }
            if(wrkMastService.getWorkingMast(devpNo)>0){
                throw new CoolException(devpNo+"站点不能同时生成两笔入库工作档");
            }
        }
        return station;
    }
src/main/java/com/zy/asrs/service/impl/BasErrLogServiceImpl.java
File was deleted
src/main/java/com/zy/asrs/service/impl/BasSteErrLogServiceImpl.java
File was deleted
src/main/java/com/zy/asrs/service/impl/BasSteErrServiceImpl.java
File was deleted
src/main/java/com/zy/asrs/service/impl/BasSteOptServiceImpl.java
File was deleted
src/main/java/com/zy/asrs/service/impl/BasSteServiceImpl.java
File was deleted
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java
Diff too large
src/main/java/com/zy/asrs/service/impl/WrkChargeServiceImpl.java
File was deleted
src/main/java/com/zy/asrs/service/impl/WrkMastServiceImpl.java
@@ -2,10 +2,11 @@
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.zy.asrs.entity.LocMast;
import com.core.common.Cools;
import com.zy.asrs.entity.WrkMast;
import com.zy.asrs.mapper.WrkMastMapper;
import com.zy.asrs.service.WrkMastService;
import com.zy.core.enums.WrkStsType;
import org.springframework.stereotype.Service;
import java.util.List;
@@ -14,18 +15,32 @@
public class WrkMastServiceImpl extends ServiceImpl<WrkMastMapper, WrkMast> implements WrkMastService {
    @Override
    public int getWorkingMast(Integer devpNo) {
        return selectCount(new EntityWrapper<WrkMast>().eq("source_sta_no", devpNo).in("wrk_sts", 1, 6));
    public WrkMast selectByWorkNo(Integer workNo) {
        return this.baseMapper.selectByWorkNo(workNo);
    }
    @Override
    public List<WrkMast> selectToBeCompleteData() {
        return this.baseMapper.selectToBeCompleteData();
    }
    @Override
    public List<WrkMast> selectToBeHistoryData() {
        return this.baseMapper.selectToBeHistoryData();
    public Boolean judgeInbound(WrkMast wrkMast) {
        switch (WrkStsType.query(wrkMast.getWrkSts())) {
            case NEW_INBOUND:
            case INBOUND_DEVICE_RUN:
            case INBOUND_LIFT_RUN:
            case INBOUND_LIFT_RUN_COMPLETE:
            case INBOUND_SHUTTLE_RUN:
            case INBOUND_SHUTTLE_RUN_COMPLETE:
            case COMPLETE_INBOUND:
            case SETTLE_INBOUND:
                return Boolean.TRUE;
            case NEW_OUTBOUND:
            case OUTBOUND_SHUTTLE_RUN:
            case OUTBOUND_SHUTTLE_RUN_COMPLETE:
            case OUTBOUND_LIFT_RUN:
            case OUTBOUND_LIFT_RUN_COMPLETE:
            case COMPLETE_OUTBOUND:
            case SETTLE_OUTBOUND:
                return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }
    @Override
@@ -42,4 +57,67 @@
    public List<WrkMast> selectShuttleOutWrkByLev(Integer lev) {
        return this.baseMapper.selectShuttleOutWrkByLev("%" + lev);
    }
    @Override
    public WrkMast selectChargeWorking(Integer shuttleNo) {
        return this.baseMapper.selectChargeWorking(shuttleNo);
    }
    @Override
    public Boolean hasBusyByShuttle(Integer shuttleNo) {
        List<WrkMast> wrkMasts = this.selectList(new EntityWrapper<WrkMast>().in("wrk_sts"
                , WrkStsType.NEW_INBOUND.sts
                , WrkStsType.INBOUND_DEVICE_RUN.sts
                , WrkStsType.INBOUND_LIFT_RUN.sts
                , WrkStsType.INBOUND_LIFT_RUN_COMPLETE.sts
                , WrkStsType.INBOUND_SHUTTLE_RUN.sts
                , WrkStsType.INBOUND_SHUTTLE_RUN_COMPLETE.sts
                , WrkStsType.NEW_OUTBOUND.sts
                , WrkStsType.OUTBOUND_SHUTTLE_RUN.sts
                , WrkStsType.OUTBOUND_SHUTTLE_RUN_COMPLETE.sts
                , WrkStsType.OUTBOUND_LIFT_RUN.sts
                , WrkStsType.OUTBOUND_LIFT_RUN_COMPLETE.sts
                , WrkStsType.NEW_MOVE.sts
                , WrkStsType.MOVE_SITE.sts
                , WrkStsType.MOVE_SITE_COMPLETE.sts
                , WrkStsType.MOVE_IN_LIFT.sts
                , WrkStsType.MOVE_IN_LIFT_COMPLETE.sts
                , WrkStsType.MOVE_LIFT_RUN.sts
                , WrkStsType.MOVE_LIFT_RUN_COMPLETE.sts
                , WrkStsType.MOVE_OUT_LIFT.sts
                , WrkStsType.MOVE_OUT_LIFT_COMPLETE.sts
                , WrkStsType.MOVE_SHUTTLE.sts
                , WrkStsType.NEW_CHARGE.sts
                , WrkStsType.CHARGE_SHUTTLE_RUN.sts
                , WrkStsType.CHARGE_SHUTTLE_WORKING.sts
                , WrkStsType.CHARGE_SHUTTLE_COMPLETE.sts
        ).eq("shuttle_no", shuttleNo));
        if (Cools.isEmpty(wrkMasts)) {
            return false;
        }
        return true;
    }
    @Override
    public WrkMast selectShuttleHasMoveWorking(Integer shuttleNo) {
        return this.baseMapper.selectShuttleHasMoveWorking(shuttleNo);
    }
    @Override
    public WrkMast selectShuttleWorking(Integer shuttleNo) {
        return this.baseMapper.selectShuttleWorking(shuttleNo);
    }
    @Override
    public List<WrkMast> selectShuttleMoveWrk() {
        return this.baseMapper.selectShuttleMoveWrk();
    }
    @Override
    public WrkMast selectLiftWrkMast(Integer liftNo) {
        return this.baseMapper.selectLiftWrkMast(liftNo);
    }
}
src/main/java/com/zy/asrs/task/ShuttlePowerEarlyWarning.java
@@ -7,9 +7,9 @@
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.SlaveType;
import com.zy.core.model.ShuttleSlave;
import com.zy.core.model.protocol.NyShuttleProtocol;
import com.zy.core.model.protocol.ShuttleProtocol;
import com.zy.core.properties.SlaveProperties;
import com.zy.core.thread.NyShuttleThread;
import com.zy.core.thread.ShuttleThread;
import com.zy.system.entity.Config;
import com.zy.system.service.ConfigService;
import lombok.extern.slf4j.Slf4j;
@@ -58,22 +58,22 @@
        boolean hasReport = false;//是否有需要报告的数据
        for (ShuttleSlave slave : slaveProperties.getShuttle()) {
            NyShuttleThread shuttleThread = (NyShuttleThread) SlaveConnection.get(SlaveType.Shuttle, slave.getId());
            ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, slave.getId());
            if (shuttleThread == null) {
                continue;
            }
            NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
            ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
            if (shuttleProtocol == null) {
                continue;
            }
            if (shuttleProtocol.getChargState() == 1) {
            if (shuttleThread.isCharging()) {
                continue;//充电中,无需通知
            }
            if (shuttleProtocol.getPowerPercent() < shuttlePowerEarlyValue) {
                buffer.append(shuttleProtocol.getShuttleNo()).append("号小车,电量").append(shuttleProtocol.getPowerPercent$()).append(",请注意。\n");
            if (Integer.parseInt(shuttleProtocol.getBatteryPower()) < shuttlePowerEarlyValue) {
                buffer.append(shuttleProtocol.getShuttleNo()).append("号小车,电量").append(shuttleProtocol.getBatteryPower()).append(",请注意。\n");
                hasReport = true;
            }
        }
src/main/java/com/zy/asrs/utils/Utils.java
@@ -1,64 +1,22 @@
package com.zy.asrs.utils;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.core.common.Arith;
import com.core.common.Cools;
import com.core.common.SpringUtils;
import com.zy.asrs.entity.BasShuttle;
import com.zy.asrs.entity.LocMast;
import com.zy.asrs.entity.WrkMast;
import com.zy.asrs.service.BasShuttleService;
import com.zy.asrs.service.LocMastService;
import com.zy.asrs.service.WrkMastService;
import com.zy.common.service.CommonService;
import com.zy.common.utils.NavigateMapData;
import com.zy.common.utils.NavigatePositionConvert;
import com.zy.common.utils.ShuttleDispatchUtils;
import com.zy.core.DevpThread;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.SlaveType;
import com.zy.core.model.DevpSlave;
import com.zy.core.model.ShuttleSlave;
import com.zy.core.model.protocol.NyShuttleProtocol;
import com.zy.core.model.protocol.StaProtocol;
import com.zy.core.model.protocol.ShuttleProtocol;
import com.zy.core.properties.SlaveProperties;
import com.zy.core.thread.NyShuttleThread;
import com.zy.core.thread.ShuttleThread;
import java.text.DecimalFormat;
import java.util.*;
import java.util.regex.Pattern;
/**
 * Created by vincent on 2020/8/27
 */
public class Utils {
    public static final List<Integer> FIRST_GROUP_ROW_LIST = new ArrayList<Integer>() {{
        add(1);
    }};
    public static final List<Integer> SECOND_GROUP_ROW_LIST = new ArrayList<Integer>() {{
        add(3);add(4);
    }};
    public static final List<Integer> THIRD_GROUP_ROW_LIST = new ArrayList<Integer>() {{
        add(6);add(7);
    }};
    public static final List<Integer> FOURTH_GROUP_ROW_LIST = new ArrayList<Integer>() {{
        add(8);
    }};
    public static final List<Integer> FIFTH_GROUP_ROW_LIST = new ArrayList<Integer>() {{
        add(10);add(11);
    }};
    public static final List<Integer> SIXTH_GROUP_ROW_LIST = new ArrayList<Integer>() {{
        add(13);add(14);add(15);add(16);
    }};
    public static final List<Integer> SEVENTH_GROUP_ROW_LIST = new ArrayList<Integer>() {{
        add(13);add(14);
    }};
    public static final List<Integer> EIGHTH_GROUP_ROW_LIST = new ArrayList<Integer>() {{
        add(16);
    }};
    private static final DecimalFormat fmt = new DecimalFormat("##0.00");
@@ -81,38 +39,6 @@
            }
            return msgBuilder.toString();
        }
    }
    public static Integer getGroupRow(String locNo, Boolean pakin){
        int row = getRow(locNo);
        return getGroupRow(row, pakin);
    }
    public static Integer getGroupRow(Integer row, Boolean pakin) {
        if (FIRST_GROUP_ROW_LIST.contains(row)) {
            return 4;
        } else if (SECOND_GROUP_ROW_LIST.contains(row)) {
            return 5;
        } else {
            return 0;
        }
//        if (pakin) {
//            if (FIRST_GROUP_ROW_LIST.contains(row)) {
//                return 2;
//            } else if (SECOND_GROUP_ROW_LIST.contains(row)) {
//                return 18;
//            } else {
//                return 0;
//            }
//        } else {
//            if (FIRST_GROUP_ROW_LIST.contains(row)) {
//                return 12;
//            } else if (SECOND_GROUP_ROW_LIST.contains(row)) {
//                return 30;
//            } else {
//                return 0;
//            }
//        }
    }
    /**
@@ -145,140 +71,16 @@
        throw new RuntimeException("库位解析异常");
    }
    /**
     * 通过排列层拼接出库位号
     */
    public static String append(int row, int bay, int lev) {
        return zerofill(String.valueOf(row), 2) + zerofill(String.valueOf(bay), 3) + zerofill(String.valueOf(lev), 2);
    }
    public static String getLocNo(Number row, Number bay, Number lev) {
        return zerofill(String.valueOf(row), 2) + zerofill(String.valueOf(bay), 3) + zerofill(String.valueOf(lev), 2);
    }
    public static void main(String[] args) {
        System.out.println(JSON.toJSONString(getGroupLoc("1606101")));
    }
    /**
     * 获取库位组
     * @param locNo 库位号
     */
    public static List<String> getGroupLoc(String locNo){
        int row = getRow(locNo);
        int bay = getBay(locNo);
        if (FIRST_GROUP_ROW_LIST.contains(row)) {
            List<String> result = new ArrayList<>();
            for (Integer row0 : FIRST_GROUP_ROW_LIST) {
                result.add(zerofill(String.valueOf(row0), 2) + locNo.substring(2));
            }
            return result;
        }
        if (SECOND_GROUP_ROW_LIST.contains(row)) {
            List<String> result = new ArrayList<>();
            for (Integer row0 : SECOND_GROUP_ROW_LIST) {
                result.add(zerofill(String.valueOf(row0), 2) + locNo.substring(2));
            }
            return result;
        }
        if (THIRD_GROUP_ROW_LIST.contains(row)) {
            List<String> result = new ArrayList<>();
            for (Integer row0 : THIRD_GROUP_ROW_LIST) {
                result.add(zerofill(String.valueOf(row0), 2) + locNo.substring(2));
            }
            Collections.reverse(result);
            return result;
        }
        if (FOURTH_GROUP_ROW_LIST.contains(row)) {
            List<String> result = new ArrayList<>();
            for (Integer row0 : FOURTH_GROUP_ROW_LIST) {
                result.add(zerofill(String.valueOf(row0), 2) + locNo.substring(2));
            }
            return result;
        }
        if (FIFTH_GROUP_ROW_LIST.contains(row)) {
            List<String> result = new ArrayList<>();
            for (Integer row0 : FIFTH_GROUP_ROW_LIST) {
                result.add(zerofill(String.valueOf(row0), 2) + locNo.substring(2));
            }
            return result;
        }
        if (SIXTH_GROUP_ROW_LIST.contains(row) && (bay >= 59 && bay <= 61)) {
            List<String> result = new ArrayList<>();
            for (Integer row0 : SIXTH_GROUP_ROW_LIST) {
                result.add(zerofill(String.valueOf(row0), 2) + locNo.substring(2));
            }
            Collections.reverse(result);
            return result;
        }
        if (SEVENTH_GROUP_ROW_LIST.contains(row) && bay < 59) {
            List<String> result = new ArrayList<>();
            for (Integer row0 : SEVENTH_GROUP_ROW_LIST) {
                result.add(zerofill(String.valueOf(row0), 2) + locNo.substring(2));
            }
            return result;
        }
        if (EIGHTH_GROUP_ROW_LIST.contains(row) && bay < 59) {
            List<String> result = new ArrayList<>();
            for (Integer row0 : EIGHTH_GROUP_ROW_LIST) {
                result.add(zerofill(String.valueOf(row0), 2) + locNo.substring(2));
            }
            return result;
        }
        throw new RuntimeException("库位解析异常");
    }
    /**
     * 获取外侧方向的库位组
     * @param locNo 库位号
     */
    public static List<String> getGroupOuterLoc(String locNo){
        int row = getRow(locNo);
        int bay = getBay(locNo);
        //(1,3,4,10,11)没有外侧方向库位组,(13,14,16)59列之内没有外侧方向库位组
        if (FIRST_GROUP_ROW_LIST.contains(row)) {//1排
            return new ArrayList<>();
        }
        if (SECOND_GROUP_ROW_LIST.contains(row)) {//3-4排
            return new ArrayList<>();
        }
        if (THIRD_GROUP_ROW_LIST.contains(row)) {//6-7排
            List<String> result = new ArrayList<>();
            for (Integer row0 : THIRD_GROUP_ROW_LIST) {
                if (row0 < row) {
                    result.add(zerofill(String.valueOf(row0), 2) + locNo.substring(2));
                }
            }
            return result;
        }
        if (FOURTH_GROUP_ROW_LIST.contains(row)) {//8排
            return new ArrayList<>();
        }
        if (FIFTH_GROUP_ROW_LIST.contains(row)) {//10-11排
            return new ArrayList<>();
        }
        if (SIXTH_GROUP_ROW_LIST.contains(row) && (bay >= 59 && bay <= 61)) {//13-16排59-61列外侧方向库位组
            List<String> result = new ArrayList<>();
            for (Integer row0 : SIXTH_GROUP_ROW_LIST) {
                if (row0 < row) {
                    result.add(zerofill(String.valueOf(row0), 2) + locNo.substring(2));
                }
            }
            return result;
        }
        if (SEVENTH_GROUP_ROW_LIST.contains(row) && bay < 59) {//13-14排59列之内没有外侧方向库位组
            return new ArrayList<>();
        }
        if (EIGHTH_GROUP_ROW_LIST.contains(row) && bay < 59) {//16排59列之内没有外侧方向库位组
            return new ArrayList<>();
        }
        throw new RuntimeException("库位解析异常");
    public static List<String> getGroupLoc(String locNo) {
        return null;
    }
    //获取除白名单外的指定楼层全部穿梭车xy坐标点
    public static List<int[]> getShuttlePoints(Integer whiteShuttle, Integer lev) {
        BasShuttleService basShuttleService = SpringUtils.getBean(BasShuttleService.class);
        SlaveProperties slaveProperties = SpringUtils.getBean(SlaveProperties.class);
        ArrayList<int[]> list = new ArrayList<>();
        for (ShuttleSlave slave : slaveProperties.getShuttle()) {
@@ -287,25 +89,18 @@
            }
            //获取穿梭车所在节点位置
            NyShuttleThread shuttleThread = (NyShuttleThread) SlaveConnection.get(SlaveType.Shuttle, slave.getId());
            ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, slave.getId());
            if (shuttleThread == null) {
                continue;
            }
            NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
            ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
            if (shuttleProtocol == null) {
                continue;
            }
            String currentLocNo = shuttleProtocol.getCurrentLocNo();
            if (currentLocNo == null) {
                //小车没有库位号数据,从数据库中取
                BasShuttle basShuttle = basShuttleService.selectById(slave.getId());
                if (basShuttle == null) {
                    continue;
                }
                NyShuttleProtocol.NyShuttlePointClass shuttlePoint = shuttleProtocol.getPoint();
                currentLocNo = NavigatePositionConvert.nyXyzToLocNo(shuttlePoint.getX(), shuttlePoint.getY(), shuttlePoint.getZ());
                continue;
            }
            if (lev != Utils.getLev(currentLocNo)) {
@@ -321,95 +116,16 @@
        return list;
    }
    //搜索一条没有小车的空巷道,并调度小车
    public static boolean searchEmptyGroupToMoveShuttle(int z, Integer currentShuttleId, NyShuttleThread shuttleThread) {
        LocMastService locMastService = SpringUtils.getBean(LocMastService.class);
        WrkMastService wrkMastService = SpringUtils.getBean(WrkMastService.class);
        CommonService commonService = SpringUtils.getBean(CommonService.class);
        ShuttleDispatchUtils shuttleDispatchUtils = SpringUtils.getBean(ShuttleDispatchUtils.class);
        NavigateMapData navigateMapData = SpringUtils.getBean(NavigateMapData.class);
        if (shuttleThread == null) {
            return false;
        }
        NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
        if (shuttleProtocol == null) {
            return false;
        }
        int[][] data = navigateMapData.getData(z, -1, null, currentShuttleId == null ? null : Utils.getShuttlePoints(0, z));//载入全部车辆
        int moveBay = 23;//避让起始列
        int bay = Utils.getBay(shuttleProtocol.getCurrentLocNo());//小车当前列
        if (bay > 1 && bay <= 30) {
            moveBay = 23;
        } else if (bay > 30 && bay <= 45) {
            moveBay = 39;
        } else if (bay > 45) {
            moveBay = 50;
        }
        int distY = -1;
        int distX = -1;
        int distZ = -1;
        //获取避让库位
        String distLocNo = null;
        for (int y = moveBay; y <= 56; y++) {
            boolean searchFlag = true;
            for (int x = 10; x <= 11; x++) {
                if (data[x][y] < 0 || data[x][y] == 66) {
                    searchFlag = false;//该巷道有禁用节点或有小车
                    break;
                }
            }
            if (searchFlag) {
                //搜索出空巷道
                distY = y;
                distX = 11;
                distZ = z;
                //获取避让库位
                String locNo = NavigatePositionConvert.xyzToLocNo(distX, distY, distZ);
                LocMast distLocMast = locMastService.queryByLoc(locNo);
                if (distLocMast == null) {
                    continue;
                }
                if (distLocMast.getLocSts().equals("X")) {
                    continue;//调过禁用库位
                }
                //判断该库位是否存在工作档
                EntityWrapper<WrkMast> wrapper = new EntityWrapper<>();
                wrapper.eq("loc_no", locNo);
                WrkMast wrkMast = wrkMastService.selectOne(wrapper);
                if (wrkMast != null) {
                    continue;//存在工作档跳过该库位
                }
                distLocNo = locNo;
                break;
            }
        }
        if (distLocNo != null) {
            //调度小车到避让位置
            return shuttleDispatchUtils.dispatchShuttle(commonService.getWorkNo(7), distLocNo, shuttleProtocol.getShuttleNo().intValue());
        }
        return false;
    }
    //检测楼层是否有穿梭车
    public static boolean checkLevHasShuttle(Integer lev) {
        SlaveProperties slaveProperties = SpringUtils.getBean(SlaveProperties.class);
        for (ShuttleSlave shuttle : slaveProperties.getShuttle()) {
            //获取四向穿梭车线程
            NyShuttleThread shuttleThread = (NyShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttle.getId());
            ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttle.getId());
            if (shuttleThread == null) {
                continue;
            }
            NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
            ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
            if (shuttleProtocol == null) {
                continue;
            }
@@ -443,12 +159,12 @@
        for (String loc : groupLoc) {
            for (ShuttleSlave slave : slaveProperties.getShuttle()) {
                NyShuttleThread shuttleThread = (NyShuttleThread) SlaveConnection.get(SlaveType.Shuttle, slave.getId());
                ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, slave.getId());
                if (shuttleThread == null) {
                    continue;
                }
                NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
                ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
                if (shuttleProtocol == null) {
                    continue;
                }
@@ -465,132 +181,5 @@
        }
        return null;
    }
    //通过提升机号和楼层获取出入库模式
    public static Integer getOutInModelByLift(Integer liftNo, Integer lev) {
        ArrayList<Integer> lev1 = new ArrayList<Integer>() {{
            add(100);add(103);
            add(105);
        }};
        ArrayList<Integer> lev2 = new ArrayList<Integer>() {{
            add(200);add(203);
            add(205);
        }};
        ArrayList<Integer> lev3 = new ArrayList<Integer>() {{
            add(341);add(346);
        }};
        Integer staNo = null;
        if (lev <= 4) {
            staNo = lev1.get(liftNo - 1);
        } else if (lev >= 5 && lev <= 7) {
            staNo = lev2.get(liftNo - 1);
        } else if ((lev >=8 && lev <= 10) && liftNo != 1) {
            staNo = lev3.get(liftNo - 2);
        }
        if (staNo != null) {
            DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, 1);
            StaProtocol staProtocol = devpThread.getStation().get(staNo);
            if (staProtocol == null) {
                return null;
            }
            if (staNo == 100 || staNo == 200) {//1号提升机100站和200站默认全是出库模式
                return 2;//出库模式
            }
            if (staNo == 341) {
                return 1;//341站默认只能入库模式
            }
            if (staProtocol.getOutInModel() == null) {
                return null;//没有出入库信号
            }
            return staProtocol.getOutInModel().intValue();
        }
        return null;
    }
    public static void wapperSetCondition(Wrapper wrapper, String column, String condition){
        if(Cools.isEmpty(condition) || "null".equals(condition)){
            wrapper.andNew().eq(column,"").or().isNull(column);
        }else {
            wrapper.eq(column,condition);
        }
    }
    /**
     * 获取内侧方向的库位组
     * @param locNo 库位号
     */
    public static List<String> getGroupInnerLoc(String locNo){
        int row = getRow(locNo);
        int bay = getBay(locNo);
        //(1,3,4,10,11)没有内侧方向库位组,(13,14,16)59列之内没有内侧方向库位组
        if (FIRST_GROUP_ROW_LIST.contains(row)) {//1排
            return new ArrayList<>();
        }
        if (SECOND_GROUP_ROW_LIST.contains(row)) {//3-4排
            return new ArrayList<>();
        }
        if (THIRD_GROUP_ROW_LIST.contains(row)) {//6-7排
            List<String> result = new ArrayList<>();
            for (Integer row0 : THIRD_GROUP_ROW_LIST) {
                if (row0 > row) {
                    result.add(zerofill(String.valueOf(row0), 2) + locNo.substring(2));
                }
            }
            return result;
        }
        if (FOURTH_GROUP_ROW_LIST.contains(row)) {//8排
            return new ArrayList<>();
        }
        if (FIFTH_GROUP_ROW_LIST.contains(row)) {//10-11排
            return new ArrayList<>();
        }
        if (SIXTH_GROUP_ROW_LIST.contains(row) && (bay >= 59 && bay <= 61)) {//13-16排59-61列内侧方向库位组
            List<String> result = new ArrayList<>();
            for (Integer row0 : SIXTH_GROUP_ROW_LIST) {
                if (row0 > row) {
                    result.add(zerofill(String.valueOf(row0), 2) + locNo.substring(2));
                }
            }
            return result;
        }
        if (SEVENTH_GROUP_ROW_LIST.contains(row) && bay < 59) {//13-14排59列之内没有内侧方向库位组
            return new ArrayList<>();
        }
        if (EIGHTH_GROUP_ROW_LIST.contains(row) && bay < 59) {//16排59列之内没有内侧方向库位组
            return new ArrayList<>();
        }
        throw new RuntimeException("库位解析异常");
    }
    /**
     * 通过入库站点号获取条码器ID
     */
    public static Integer getBarcodeIdByStaNo(int staNo) {
        SlaveProperties slaveProperties = SpringUtils.getBean(SlaveProperties.class);
        for (DevpSlave devpSlave : slaveProperties.getDevp()) {
            for (DevpSlave.Sta sta : devpSlave.getInSta()) {
                if (sta.getStaNo().equals(staNo)) {
                    return sta.getBarcode();
                }
            }
        }
        return null;
    }
    /**
     * 判断字符串是否为JSON格式
     */
    public static boolean isJson(String jsonString) {
        // JSON格式的正则表达式
        String pattern = "^\\{.*\\}$";
        // 使用Pattern类进行正则匹配
        return Pattern.matches(pattern, jsonString);
    }
}
src/main/java/com/zy/asrs/ws/ConsoleWebSocket.java
@@ -4,7 +4,7 @@
import com.core.common.R;
import com.core.common.SpringUtils;
import com.zy.asrs.controller.ConsoleController;
import com.zy.asrs.controller.LiftController;
import com.zy.asrs.controller.ForkLiftController;
import com.zy.asrs.controller.ShuttleController;
import com.zy.common.model.WebSocketMessage;
import lombok.Data;
@@ -71,7 +71,7 @@
    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
        ShuttleController shuttleController = SpringUtils.getBean(ShuttleController.class);
        LiftController liftController = SpringUtils.getBean(LiftController.class);
        ForkLiftController liftController = SpringUtils.getBean(ForkLiftController.class);
        ConsoleController consoleController = SpringUtils.getBean(ConsoleController.class);
        WebSocketMessage socketMessage = JSON.parseObject(message, WebSocketMessage.class);
        if (socketMessage.getUrl().equals("/shuttle/table/shuttle/state")) {
@@ -91,7 +91,7 @@
            socketMessage.setData(JSON.toJSONString(result));
            this.sendMessage(JSON.toJSONString(socketMessage));
        } else if (socketMessage.getUrl().equals("/console/barcode/output/site")) {
            R result = consoleController.crnOutput();
            R result = consoleController.barcodeOutput();
            socketMessage.setData(JSON.toJSONString(result));
            this.sendMessage(JSON.toJSONString(socketMessage));
        }
src/main/java/com/zy/common/ExecuteSupport.java
New file
@@ -0,0 +1,7 @@
package com.zy.common;
public interface ExecuteSupport {
    Boolean judgement();
}
src/main/java/com/zy/common/model/MapNode.java
@@ -6,8 +6,19 @@
 * 地图数据节点
 */
@Data
public class MapNode {
public class MapNode implements Cloneable {
    /**
     * -1 禁用
     * 0 子轨道
     * 3 母轨道
     * 4 输送站点
     * 5 充电桩
     * 6 小车可走输送站点
     * 66 穿梭车坐标
     * 67 提升机坐标
     * -999 锁定节点
     */
    private Integer value;
    private String data;
@@ -20,4 +31,29 @@
    private Integer right;
}
    private String no;
    private Integer row;
    private Integer bay;
    //节点被锁定时所属设备号
    private Integer lockDeviceNo;
    //**************兼容牛眼新协议**************//
    private Integer xBase;//x基准
    private Integer yBase;//y基准
    //**************兼容牛眼新协议**************//
    @Override
    public MapNode clone() {
        try {
            return (MapNode) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
}
src/main/java/com/zy/common/model/NavigateNode.java
@@ -2,11 +2,13 @@
import lombok.Data;
import java.io.Serializable;
/**
 * A*寻路算法Node节点
 */
@Data
public class NavigateNode implements Comparable<NavigateNode>{
public class NavigateNode implements Comparable<NavigateNode>, Cloneable, Serializable {
    private int x;//坐标x
    private int y;//坐标y
@@ -46,4 +48,14 @@
        return Integer.compare(this.F, o.F);
    }
    @Override
    public NavigateNode clone() {
        try {
            return (NavigateNode) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
}
src/main/java/com/zy/common/model/ShuttleOperaResult.java
File was renamed from src/main/java/com/zy/common/model/NyShuttleOperaResult.java
@@ -7,13 +7,13 @@
@Data
//结果集
public class NyShuttleOperaResult {
public class ShuttleOperaResult {
    //命令集合
    private List<NyShuttleHttpCommand> commands;
    //行走路径集合
    private List<NavigateNode> nodes;
    public NyShuttleOperaResult(List<NyShuttleHttpCommand> commands, List<NavigateNode> nodes) {
    public ShuttleOperaResult(List<NyShuttleHttpCommand> commands, List<NavigateNode> nodes) {
        this.commands = commands;
        this.nodes = nodes;
    }
src/main/java/com/zy/common/service/CommonService.java
@@ -8,10 +8,6 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
 * 货架核心功能
 * Created by vincent on 2020/6/11
 */
@Slf4j
@Service
public class CommonService {
@@ -20,9 +16,6 @@
    private WrkMastService wrkMastService;
    @Autowired
    private WrkLastnoService wrkLastnoService;
    @Autowired
    private WrkChargeService wrkChargeService;
    /**
     * 生成工作号
@@ -57,40 +50,6 @@
        } else {
            if (wrkMastService.selectById(workNo)!=null) {
                throw new CoolException("生成工作号" + workNo + "在工作档中已存在");
            }
        }
        return workNo;
    }
    public int getChargeWorkNo(Integer wrkMk) {
        WrkLastno wrkLastno = wrkLastnoService.selectById(wrkMk);
        if (Cools.isEmpty(wrkLastno)) {
            throw new CoolException("数据异常,请联系管理员");
        }
        int workNo = wrkLastno.getWrkNo();
        int sNo = wrkLastno.getSNo();
        int eNo = wrkLastno.getENo();
        workNo = workNo>=eNo ? sNo : workNo+1;
        while (true) {
            WrkCharge wrkCharge = wrkChargeService.selectById(workNo);
            if (null != wrkCharge) {
                workNo = workNo>=eNo ? sNo : workNo+1;
            } else {
                break;
            }
        }
        // 修改序号记录
        if (workNo > 0){
            wrkLastno.setWrkNo(workNo);
            wrkLastnoService.updateById(wrkLastno);
        }
        // 检验
        if (workNo == 0) {
            throw new CoolException("生成充电工作号失败,请联系管理员");
        } else {
            if (wrkChargeService.selectById(workNo)!=null) {
                throw new CoolException("生成工作号" + workNo + "在充电工作档中已存在");
            }
        }
        return workNo;
src/main/java/com/zy/common/utils/ForkLiftOperaUtils.java
New file
@@ -0,0 +1,26 @@
package com.zy.common.utils;
import com.zy.core.model.command.ForkLiftCommand;
import org.springframework.stereotype.Component;
/**
 * 货叉提升机操作工具类
 */
@Component
public class ForkLiftOperaUtils {
    /**
     * 获取提升机命令
     */
    public ForkLiftCommand getLiftCommand(Integer liftNo, Integer taskNo, Integer taskModel, Integer pick, Integer put, Integer confirm) {
        ForkLiftCommand command = new ForkLiftCommand();
        command.setLiftNo(liftNo);
        command.setTaskNo(taskNo.shortValue());
        command.setMode(taskModel.shortValue());
        command.setPick(pick.shortValue());
        command.setPut(put.shortValue());
        command.setConfirm(confirm.shortValue());
        return command;
    }
}
src/main/java/com/zy/common/utils/ForkLiftUtils.java
New file
@@ -0,0 +1,74 @@
package com.zy.common.utils;
import com.core.common.SpringUtils;
import com.zy.asrs.utils.Utils;
import com.zy.common.model.NavigateNode;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.SlaveType;
import com.zy.core.model.ForkLiftSlave;
import com.zy.core.model.protocol.ForkLiftStaProtocol;
import com.zy.core.properties.SlaveProperties;
import com.zy.core.thread.ForkLiftThread;
import java.util.ArrayList;
import java.util.List;
/**
 * 货叉提升机工具类
 */
public class ForkLiftUtils {
    //获取提升机站点
    public static ForkLiftStaProtocol getLiftStaByStaNo(Integer staNo) {
        SlaveProperties slaveProperties = SpringUtils.getBean(SlaveProperties.class);
        for (ForkLiftSlave liftSlave : slaveProperties.getForkLift()) {
            ForkLiftThread forkLiftThread = (ForkLiftThread) SlaveConnection.get(SlaveType.ForkLift, liftSlave.getId());
            if (forkLiftThread == null) {
                return null;
            }
            for (ForkLiftStaProtocol forkLiftStaProtocol : forkLiftThread.getForkLiftStaProtocols()) {
                if (forkLiftStaProtocol.getStaNo().equals(staNo)) {
                    return forkLiftStaProtocol;
                }
            }
        }
        return null;
    }
    //获取提升机站点
    public static ForkLiftStaProtocol getLiftStaByLev(Integer liftNo, Integer lev) {
        ForkLiftThread forkLiftThread = (ForkLiftThread) SlaveConnection.get(SlaveType.ForkLift, liftNo);
        if (forkLiftThread == null) {
            return null;
        }
        for (ForkLiftStaProtocol forkLiftStaProtocol : forkLiftThread.getForkLiftStaProtocols()) {
            if (forkLiftStaProtocol.getLev().equals(lev)) {
                return forkLiftStaProtocol;
            }
        }
        return null;
    }
    //获取提升机输送站及其前一站节点
    public static List<NavigateNode> getLiftStaNodes(Integer staNo) {
        List<NavigateNode> targetNodes = new ArrayList<>();
        //获取目标站
        ForkLiftStaProtocol targetLiftSta = ForkLiftUtils.getLiftStaByStaNo(staNo);
        if (targetLiftSta == null) {
            return null;//找不到站点
        }
        NavigateNode targetNode = NavigatePositionConvert.locNoToNode(targetLiftSta.getLocNo());//目标节点
        String targetLastLocNo = Utils.getLocNo(Utils.getRow(targetLiftSta.getLocNo()) - 1, Utils.getBay(targetLiftSta.getLocNo()), Utils.getLev(targetLiftSta.getLocNo()));//目标节点前一站
        NavigateNode targetLastNode = NavigatePositionConvert.locNoToNode(targetLastLocNo);//目标节点前一站
        targetNodes.add(targetNode);
        targetNodes.add(targetLastNode);
        return targetNodes;
    }
}
src/main/java/com/zy/common/utils/NavigateMapData.java
@@ -1,24 +1,18 @@
package com.zy.common.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.core.common.SpringUtils;
import com.zy.asrs.entity.BasMap;
import com.zy.asrs.entity.LocMast;
import com.zy.asrs.service.BasShuttleService;
import com.zy.asrs.service.LocMastService;
import com.zy.common.model.MapNode;
import com.zy.common.model.NavigateNode;
import com.zy.common.model.enums.NavigationMapType;
import com.zy.core.enums.RedisKeyType;
import com.zy.core.enums.ShuttleTaskModeType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import java.io.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
@@ -26,16 +20,6 @@
 */
@Component
public class NavigateMapData {
//    private Integer lev;//地图楼层
//
//    public Integer getLev() {
//        return lev;
//    }
//
//    public void setLev(Integer lev) {
//        this.lev = lev;
//    }
    public int[][] getData(Integer lev, Integer mapType, List<int[]> whitePoints, List<int[]> shuttlePoints) {
        try {
src/main/java/com/zy/common/utils/NavigatePositionConvert.java
@@ -1,9 +1,8 @@
package com.zy.common.utils;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.SpringUtils;
import com.zy.asrs.entity.BasDevp;
import com.zy.asrs.entity.LocMast;
import com.zy.asrs.service.BasDevpService;
import com.zy.asrs.service.LocMastService;
import com.zy.asrs.utils.Utils;
import com.zy.common.model.NavigateNode;
@@ -13,6 +12,34 @@
 */
public class NavigatePositionConvert {
    public static String xyToPosition(int x, int y, int z) {
        String locNo = Utils.getLocNo(x, y, z);
        //库位号转小车二维码
        LocMastService locMastService = SpringUtils.getBean(LocMastService.class);
        LocMast locMast = locMastService.selectOne(new EntityWrapper<LocMast>()
                .eq("loc_no", locNo)
                .eq("status", 1));
        if (locMast == null) {
            return null;
        }
        return locMast.getQrCodeValue();
    }
    //小车条形码转路径算法节点
    public static NavigateNode codeToNode(String code) {
        LocMastService locMastService = SpringUtils.getBean(LocMastService.class);
        LocMast locMast = locMastService.selectOne(new EntityWrapper<LocMast>()
                .eq("qr_code_value", code)
                .eq("status", 1));
        if (locMast == null) {
            return null;
        }
        NavigateNode node = new NavigateNode(locMast.getRow1(), locMast.getBay1());
        node.setZ(locMast.getLev1());
        return node;
    }
    //坐标编号转xy轴
    public static int[] positionToXY(String position) {
        int col = Integer.parseInt(position.substring(0, 2));
src/main/java/com/zy/common/utils/NavigateSolution.java
@@ -1,27 +1,38 @@
package com.zy.common.utils;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.SpringUtils;
import com.core.exception.CoolException;
import com.zy.common.model.NavigateNode;
import com.zy.core.enums.MapNodeType;
import com.zy.core.model.PythonResult;
import com.zy.system.entity.Config;
import com.zy.system.service.ConfigService;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;
/**
 * 四向库核心
 * A*算法实现类
 */
public class NavigateSolution {
    // -1 -> 墙壁, 1 -> 起点  2 -> 终点  3-> 母轨  4->站点
    // -1 -> 墙壁, 0 -> 货位, 1 -> 起点  2 -> 终点  3-> 母轨  4->输送站点  5->充电桩 6->小车可走输送站点  66->小车  67->提升机
    int[][] map = {{}};
    public NavigateSolution(Integer mapType, Integer lev, List<int[]> whitePoints, List<int[]> shuttlePoints) {
        //载入地图指定层高地图
        NavigateMapData navigateMapData = SpringUtils.getBean(NavigateMapData.class);
        int[][] data = navigateMapData.getDataFromRedis(lev, mapType, whitePoints, shuttlePoints);
        NavigateMapData mapData = SpringUtils.getBean(NavigateMapData.class);
        int[][] data = mapData.getDataFromRedis(lev, mapType, whitePoints, shuttlePoints);
        if (data == null) {
            data = navigateMapData.getData(lev, mapType, whitePoints, shuttlePoints);
            throw new CoolException("地图未载入!");
        }
        this.map = data;
    }
@@ -37,56 +48,115 @@
    //Exist表用来存放已经出现过的结点。
    public ArrayList<NavigateNode> Exist = new ArrayList<NavigateNode>();
    public NavigateNode astarSearch(NavigateNode start, NavigateNode end) {
        //把第一个开始的结点加入到Open表中
        this.Open.add(start);
        //把出现过的结点加入到Exist表中
        this.Exist.add(start);
        //主循环
        while (Open.size() > 0) {
            //取优先队列顶部元素并且把这个元素从Open表中删除
            NavigateNode current_node = Open.poll();
            //将这个结点加入到Close表中
            Close.add(current_node);
            //对当前结点进行扩展,得到一个四周结点的数组
            ArrayList<NavigateNode> neighbour_node = extend_current_node(current_node);
            //对这个结点遍历,看是否有目标结点出现
            for (NavigateNode node : neighbour_node) {
                // G + H + E (对启发函数增加去拐点方案calcNodeExtraCost)
                int gCost = calcNodeCost(current_node, node) + calcNodeExtraCost(current_node, node, end);
                if (node.getX() == end.getX() && node.getY() == end.getY()) {//找到目标结点就返回
                    //init_node操作把这个邻居结点的父节点设置为当前结点
                    //并且计算出G, F, H等值
                    node.init_node(current_node, end);
                    return node;
                }
    public String astarSearch(NavigateNode start, NavigateNode end, String pythonScriptPath) {
        String maps = JSON.toJSONString(map);
        String startStr = start.getX() + "-" + start.getY();
        String targetStr = end.getX() + "-" + end.getY();
                //(对启发函数增加去拐点方案calcNodeExtraCost)
                if (is_exist(node)) {
                    if (gCost < node.getG()) {
                        node.setFather(current_node);
                        node.setG(gCost);
                        node.setF(node.getG() + node.getH());
                    }
                }else {
                    //没出现过的结点加入到Open表中并且设置父节点
                    //进行计算对G, F, H 等值
                    node.init_node(current_node, end);
                    node.setG(gCost);
                    node.setH(calcNodeCost(node, end));
                    node.setF(node.getG() + node.getH());
                    Open.add(node);
                    Exist.add(node);
                }
        //默认地图母轨方向x
        String mapDirection = "x";
        ConfigService configService = SpringUtils.getBean(ConfigService.class);
        if (configService != null) {
            Config config = configService.selectOne(new EntityWrapper<Config>()
                    .eq("code", "direction_map")
                    .eq("status", 1));
            if (config != null) {
                mapDirection = config.getValue();
            }
        }
        //如果遍历完所有出现的结点都没有找到最终的结点,返回null
        ProcessBuilder processBuilder = new ProcessBuilder("python", pythonScriptPath, maps, startStr, targetStr, mapDirection);
        processBuilder.redirectErrorStream(true);
        try {
            Process process = processBuilder.start();
            // 读取Python脚本的输出
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            StringBuilder builder = new StringBuilder();
            while ((line = reader.readLine()) != null) {
                builder.append(line);
            }
            // 等待Python脚本执行完成
            int exitCode = process.waitFor();
            if (exitCode != 0) {
                System.out.println("Python script exited with error code: " + exitCode);
                return null;
            }
            reader.close();
            if (builder.length() <= 0) {
                return null;
            }
            PythonResult result = JSON.parseObject(builder.toString(), PythonResult.class);
            if (result.getCalcResult() != 200) {
                return null;
            }
            String path = result.getPath();
            return path;
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }
//    public NavigateNode astarSearch(NavigateNode start, NavigateNode end) {
//        //把第一个开始的结点加入到Open表中
//        this.Open.add(start);
//        //把出现过的结点加入到Exist表中
//        this.Exist.add(start);
//        //主循环
//        while (Open.size() > 0) {
//            //取优先队列顶部元素并且把这个元素从Open表中删除
//            NavigateNode current_node = Open.poll();
//            //将这个结点加入到Close表中
//            Close.add(current_node);
//            //对当前结点进行扩展,得到一个四周结点的数组
//            ArrayList<NavigateNode> neighbour_node = extend_current_node(current_node);
//            //对这个结点遍历,看是否有目标结点出现
//            for (NavigateNode node : neighbour_node) {
//                // G + H + E (对启发函数增加去拐点方案calcNodeExtraCost)
//                int gCost = calcNodeCost(current_node, node) * calcNodeExtraCost(current_node, node, end);
//                if (node.getX() == end.getX() && node.getY() == end.getY()) {//找到目标结点就返回
//                    //init_node操作把这个邻居结点的父节点设置为当前结点
//                    //并且计算出G, F, H等值
//                    node.setLastDistance(gCost);
//                    node.init_node(current_node, end);
//                    return node;
//                }
//
//                //进行计算对G, F, H 等值
//                node.setLastDistance(gCost);
//                node.init_node(current_node, end);
//                node.setH(calcNodeCost(node, end));
//                node.setF(node.getG() + node.getH());
//
//                Open.add(node);
//                Exist.add(node);
//            }
//        }
//        //如果遍历完所有出现的结点都没有找到最终的结点,返回null
//        return null;
//    }
    public ArrayList<NavigateNode> extend_current_node(NavigateNode current_node) {
        //默认地图母轨方向x
        String mapDirection = "x";
        ConfigService configService = SpringUtils.getBean(ConfigService.class);
        if (configService != null) {
            Config config = configService.selectOne(new EntityWrapper<Config>()
                    .eq("config", "direction_map")
                    .eq("status", 1));
            if (config != null) {
                mapDirection = config.getValue();
            }
        }
        //获取当前结点的x, y
        int x = current_node.getX();
        int y = current_node.getY();
@@ -119,31 +189,62 @@
//                neighbour_node.add(node);
//            }
//        }
        if (map[x][y] == 3) {
            //母轨才能进行左右移动
            if (is_valid(x, y + 1))
            {
                NavigateNode node = new NavigateNode(x, y + 1);
                neighbour_node.add(node);
            }
            if (is_valid(x, y - 1))
            {
                NavigateNode node = new NavigateNode(x, y - 1);
                neighbour_node.add(node);
            }
        }
        if (map[x][y] == 0 || map[x][y] == 3 || map[x][y] == 4 || map[x][y] == 5) {
            //子轨和母轨、输送线、充电桩才能进行上下移动
            if (is_valid(x + 1, y))
            {
                NavigateNode node = new NavigateNode(x + 1, y);
                neighbour_node.add(node);
        if (mapDirection.equals("x")) {//母轨x方向
            if (map[x][y] == MapNodeType.MAIN_PATH.id) {
                //母轨才能进行上下移动
                if (is_valid(x + 1, y))
                {
                    NavigateNode node = new NavigateNode(x + 1, y);
                    neighbour_node.add(node);
                }
                if (is_valid(x - 1, y))
                {
                    NavigateNode node = new NavigateNode(x -1, y);
                    neighbour_node.add(node);
                }
            }
            if (is_valid(x - 1, y))
            {
                NavigateNode node = new NavigateNode(x -1, y);
                neighbour_node.add(node);
            if (map[x][y] == MapNodeType.NORMAL_PATH.id || map[x][y] == MapNodeType.MAIN_PATH.id || map[x][y] == MapNodeType.CONVEYOR_CAR_GO.id || map[x][y] == MapNodeType.CHARGE.id || map[x][y] == MapNodeType.LIFT.id) {
                //子轨和母轨、小车可走输送线、充电桩、提升机才能进行左右移动
                if (is_valid(x, y + 1))
                {
                    NavigateNode node = new NavigateNode(x, y + 1);
                    neighbour_node.add(node);
                }
                if (is_valid(x, y - 1))
                {
                    NavigateNode node = new NavigateNode(x, y - 1);
                    neighbour_node.add(node);
                }
            }
        }else if (mapDirection.equals("y")) {//母轨y方向
            if (map[x][y] == MapNodeType.MAIN_PATH.id) {
                //母轨才能进行左右移动
                if (is_valid(x, y + 1))
                {
                    NavigateNode node = new NavigateNode(x, y + 1);
                    neighbour_node.add(node);
                }
                if (is_valid(x, y - 1))
                {
                    NavigateNode node = new NavigateNode(x, y - 1);
                    neighbour_node.add(node);
                }
            }
            if (map[x][y] == MapNodeType.NORMAL_PATH.id || map[x][y] == MapNodeType.MAIN_PATH.id || map[x][y] == MapNodeType.CONVEYOR_CAR_GO.id || map[x][y] == MapNodeType.CHARGE.id || map[x][y] == MapNodeType.LIFT.id) {
                //子轨和母轨、小车可走输送线、充电桩、提升机才能进行上下移动
                if (is_valid(x + 1, y))
                {
                    NavigateNode node = new NavigateNode(x + 1, y);
                    neighbour_node.add(node);
                }
                if (is_valid(x - 1, y))
                {
                    NavigateNode node = new NavigateNode(x -1, y);
                    neighbour_node.add(node);
                }
            }
        }
@@ -151,16 +252,21 @@
    }
    public boolean is_valid(int x, int y) {
        if (x < 0 || x >= this.map.length
                || y < 0 || y >= this.map[0].length) {
            return false;
        }
        // 如果结点的位置小于0,则不合法
        if (map[x][y] < 0) return false;
        for (NavigateNode node : Exist) {
            //如果结点出现过,不合法
            if (node.getX() == x && node.getY() == y) {
                return false;
            }
            if (is_exist(new NavigateNode(x, y))) {
                return false;
            }
        if (map[x][y] < 0) {
            return false;
        }
        if (map[x][y] == MapNodeType.CAR.id) {//节点是小车
            return false;
        }
        NavigateNode navigateNode = new NavigateNode(x, y);
        if (is_exist(navigateNode)) {
            return false;
        }
        //以上情况都没有则合法
        return true;
@@ -188,23 +294,12 @@
        // 第一个点或直线点
        if (currNode.getFather() == null || nextNode.getX() == currNode.getFather().getX()
                || nextNode.getY() == currNode.getFather().getY()) {
            return 0;
            return 1;
        }
        // 拐向终点的点
        if (nextNode.getX() == endNode.getX() || nextNode.getY() == endNode.getY()) {
            return 1;
        }
        // 拐向主轨道的点
        if (map[nextNode.getX()][nextNode.getY()] == 3) {
            //------------------三凯独特判断------------------//
            if (nextNode.getX() == 15) {
                return 2;//影响算法,不要在15排这个主轨道换向
            }
            //------------------三凯独特判断------------------//
            return 0;
            return 2;
        }
        // 普通拐点
src/main/java/com/zy/common/utils/NavigateUtils.java
@@ -1,24 +1,35 @@
package com.zy.common.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.core.common.SpringUtils;
import com.zy.asrs.utils.Utils;
import com.zy.common.model.MapNode;
import com.zy.common.model.NavigateNode;
import com.zy.common.model.enums.NavigationMapType;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.ShuttleTaskModeType;
import com.zy.core.enums.SlaveType;
import com.zy.core.model.protocol.NyShuttleProtocol;
import com.zy.core.thread.NyShuttleThread;
import com.zy.core.News;
import com.zy.core.enums.MapNodeType;
import com.zy.core.model.PythonSimilarityResult;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;
/**
 * A*算法使用工具
 */
@Component
public class NavigateUtils {
    public static List<NavigateNode> calc(String startPoint, String endPoint, Integer mapType, List<int[]> shuttlePoints, List<int[]> whites) {
    @Value("${pythonCalcPath}")
    private String pythonCalcPath;
    @Value("${pythonCalcSimilarity}")
    private String pythonCalcSimilarity;
    public List<NavigateNode> calc(String startPoint, String endPoint, Integer mapType, List<int[]> shuttlePoints, List<int[]> whites) {
        //通过开始编号和结束编号获取对应的xy轴坐标
        int[] startArr = NavigatePositionConvert.positionToXY(startPoint);//开始节点
        int[] endArr = NavigatePositionConvert.positionToXY(endPoint);//结束节点
@@ -41,56 +52,61 @@
        NavigateSolution solution = new NavigateSolution(mapType, lev, whiteList, shuttlePoints);
        //开始节点,不纳入禁用节点内计算
        NavigateNode res_node = solution.astarSearch(start, end);
        if (res_node == null) {
            System.out.println(start + "," + end + ":未找到路径");
        String pathStr = solution.astarSearch(start, end, pythonCalcPath);
        if (pathStr == null) {
            News.error("{} dash {} can't find navigate path!", startPoint, endPoint);
            return null;
        } else {
            ArrayList<NavigateNode> list = new ArrayList<>();
            //渲染
            NavigateNode fatherNode = null;//当前循环上一节点,用于拐点计算
            while (res_node != null) {
                res_node.setDirection(null);
                res_node.setIsInflectionPoint(false);
                res_node.setZ(lev);//设置层高
                //寻找拐点
                HashMap<String, Object> result = searchInflectionPoint(res_node, fatherNode, res_node.getFather());//分别传入当前节点、父节点、下一节点
                //判断当前节点是否为拐点
                if (Boolean.parseBoolean(result.get("result").toString())) {
                    //当前为拐点
                    res_node.setIsInflectionPoint(true);
                    //拐点方向
                    res_node.setDirection(result.get("direction").toString());
                }
                list.add(res_node);
                fatherNode = res_node;//把当前节点保存成一个父节点
                res_node = res_node.getFather();//迭代操作
            }
            Collections.reverse(list);
            //将每个节点里面的fatherNode至为null(方便后续计算时父节点过多导致显示的节点太多)
            for (NavigateNode navigateNode : list) {
                //父节点设置为null,不影响计算结果,不影响后续操作。
                //此操作仅为后续排查处理提供视觉方便。
                navigateNode.setFather(null);
            }
            //起始节点计算方向
            String direction = calcDirection(list.get(0), list.get(1));
            NavigateNode startNode = list.get(0);
            startNode.setDirection(direction);
            //更新节点列表
            list.set(0, startNode);
            return list;
        }
        List<NavigateNode> list = new ArrayList<>();
        NavigateNode fatherNode = null;//当前循环上一节点,用于拐点计算
        JSONArray rows = JSON.parseArray(pathStr);
        for (int i = 0; i < rows.size(); i++) {
            Object currentObj = rows.get(i);
            NavigateNode nextNode = null;
            if ((i + 1) < rows.size()) {
                Object object = rows.get(i + 1);
                nextNode = pythonObjTransferNode(object, lev);
            }
            NavigateNode node = pythonObjTransferNode(currentObj, lev);
            //寻找拐点
            HashMap<String, Object> result = searchInflectionPoint(node, fatherNode, nextNode);//分别传入当前节点、父节点、下一节点
            //判断当前节点是否为拐点
            if (Boolean.parseBoolean(result.get("result").toString())) {
                //当前为拐点
                node.setIsInflectionPoint(true);
                //拐点方向
                node.setDirection(result.get("direction").toString());
            }
            list.add(node);
            fatherNode = node;//把当前节点保存成一个父节点
        }
        //将每个节点里面的fatherNode至为null(方便后续计算时父节点过多导致显示的节点太多)
        for (NavigateNode navigateNode : list) {
            //父节点设置为null,不影响计算结果,不影响后续操作。
            //此操作仅为后续排查处理提供视觉方便。
            navigateNode.setFather(null);
        }
        //起始节点计算方向
        String direction = calcDirection(list.get(0), list.get(1));
        NavigateNode startNode = list.get(0);
        startNode.setDirection(direction);
        //更新节点列表
        list.set(0, startNode);
        return list;
    }
    //判断当前节点到下一个节点是否为拐点
    public static HashMap<String,Object> searchInflectionPoint(NavigateNode currentNode, NavigateNode fatherNode, NavigateNode nextNode) {
    public HashMap<String,Object> searchInflectionPoint(NavigateNode currentNode, NavigateNode fatherNode, NavigateNode nextNode) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("result", false);//是否为拐点,true:拐点,false:直线
        // 第一个点或直线点
@@ -109,7 +125,7 @@
    /**
     * 计算方向
     */
    public static String calcDirection(NavigateNode currentNode, NavigateNode fatherNode) {
    public String calcDirection(NavigateNode currentNode, NavigateNode fatherNode) {
        //拐点方向
        String direction = "";
        // 普通拐点
@@ -142,30 +158,30 @@
    }
    /**
     * 加转弯节点
     * 获取分段路径,每当有一个拐点则进行一次分段,最终返回总分段数据
     */
    public static ArrayList<ArrayList<NavigateNode>> getSectionPath(List<NavigateNode> mapList) {
    public ArrayList<ArrayList<NavigateNode>> getSectionPath(List<NavigateNode> mapList) {
        ArrayList<ArrayList<NavigateNode>> list = new ArrayList<>();
        ArrayList<NavigateNode> data = new ArrayList<>();
        String direction = mapList.get(0).getDirection();//行走方向
        for (int i = 0; i < mapList.size(); i++) {
            NavigateNode mapNode = mapList.get(i);
            boolean isInflectionPoint = mapNode.getIsInflectionPoint();
            data.add(mapNode);
            if (isInflectionPoint) {
                //拐点
        for (NavigateNode navigateNode : mapList) {
            data.add(navigateNode);
            //拐点
            if (navigateNode.getIsInflectionPoint()) {
                //分割数据
                list.add(data);//添加某一段数据
                direction = mapNode.getDirection();//更新行走方向
                direction = navigateNode.getDirection();//更新行走方向
                data = new ArrayList<>();
                data.add(mapNode);//将拐点的终点,更新成下一段命令的起点坐标
            }else {
                data.add(navigateNode);//将拐点的终点,更新成下一段命令的起点坐标
            } else {
                //直行线路
                mapNode.setDirection(direction);//设置行走方向
                navigateNode.setDirection(direction);//设置行走方向
            }
            Integer distance = getXToNextDistance(mapNode);//获取当前点到下一点的行走距离
            mapNode.setMoveDistance(distance);
            Integer distance = getXToNextDistance(navigateNode);//获取当前点到下一点的行走距离
            navigateNode.setMoveDistance(distance);
        }
        //将最后一段数据添加进入
@@ -175,10 +191,9 @@
    }
    //获取从x点到下一点的行走距离
    public static Integer getXToNextDistance(NavigateNode xNode) {
        NavigateMapData navigateMapData = SpringUtils.getBean(NavigateMapData.class);
        List<List<MapNode>> lists = navigateMapData.getJsonData(xNode.getZ(), NavigationMapType.NONE.id, null, null);
    public Integer getXToNextDistance(NavigateNode xNode) {
        NavigateMapData mapData = SpringUtils.getBean(NavigateMapData.class);
        List<List<MapNode>> lists = mapData.getJsonData(xNode.getZ(), NavigationMapType.NONE.id, null, null);
        if (lists != null) {
            MapNode mapNode = lists.get(xNode.getX()).get(xNode.getY());
            if (mapNode != null) {
@@ -201,11 +216,11 @@
    /**
     * 根据原始节点结果,计算总行走距离
     */
    public static Integer getOriginPathAllDistance(List<NavigateNode> path) {
        ArrayList<ArrayList<NavigateNode>> sectionPath = NavigateUtils.getSectionPath(path);
    public Integer getOriginPathAllDistance(List<NavigateNode> path) {
        ArrayList<ArrayList<NavigateNode>> sectionPath = getSectionPath(path);
        Integer allDistance = 0;
        for (ArrayList<NavigateNode> navigateNodes : sectionPath) {
            Integer distance = NavigateUtils.getCurrentPathAllDistance(navigateNodes);
            Integer distance = getCurrentPathAllDistance(navigateNodes);
            allDistance += distance;
        }
        return allDistance;
@@ -214,7 +229,7 @@
    /**
     * 获取当前路径总行走距离
     */
    public static Integer getCurrentPathAllDistance(List<NavigateNode> path) {
    public Integer getCurrentPathAllDistance(List<NavigateNode> path) {
        if (path.size() == 1) {
            //路径只有一条数据,则直接返回行走距离
            return path.get(0).getMoveDistance();
@@ -231,7 +246,7 @@
    /**
     * 获取中间点到目标点行走距离
     */
    public static Integer getMiddleToDistDistance(List<NavigateNode> path, NavigateNode middlePath) {
    public Integer getMiddleToDistDistance(List<NavigateNode> path, NavigateNode middlePath) {
        //最后一条节点不计算进行走距离
        NavigateNode lastPath = path.get(path.size() - 1);
        //总距离
@@ -256,46 +271,95 @@
    /**
     * 检测路径是否可用(可走)
     */
    public static boolean checkPathIsAvailable(List<NavigateNode> path, Integer shuttleNo, Integer lev, List<int[]> whitePoints) {
        NyShuttleThread shuttleThread = (NyShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
        if (shuttleThread == null) {
            return false;
        }
        NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
        if (shuttleProtocol == null) {
            return false;
        }
        Integer mapType = NavigationMapType.DFX.id;
        if (shuttleProtocol.getLiftPosition() == 1) {
            //下降位置
            mapType = NavigationMapType.NORMAL.id;
        }
        NavigateSolution solution = new NavigateSolution(mapType, lev, whitePoints, Utils.getShuttlePoints(shuttleNo, lev));//获取无白名单地图(该地图包含小车坐标)
    public boolean checkPathIsAvailable(List<NavigateNode> path, Integer shuttleNo, Integer lev) {
        NavigateSolution solution = new NavigateSolution(NavigationMapType.DFX.id, lev, null, Utils.getShuttlePoints(shuttleNo, lev));//获取无白名单地图(该地图包含小车坐标)
        int[][] map = solution.map;
        for (NavigateNode node : path) {
            int value = map[node.getX()][node.getY()];
            if (value != 0 && value != 3 && value != 5) {//母轨道3、子轨道0、充电桩5
            if (value != MapNodeType.NORMAL_PATH.id && value != MapNodeType.MAIN_PATH.id && value != MapNodeType.CHARGE.id && value != MapNodeType.CONVEYOR_CAR_GO.id) {//母轨道3、子轨道0、充电桩5、小车可走输送站
                return false;
            }
        }
        return true;
    }
    public static void main(String[] args) {
        //计算路径
        List<NavigateNode> calc = calc("1000901", "1800201", NavigationMapType.NONE.id, null, null);
        System.out.println(calc);
        System.out.println("------------------------");
//        List<NavigateNode> calc = calc("0501401", "0201801", "out");
        //将路径分割成多段
        ArrayList<ArrayList<NavigateNode>> data = getSectionPath(calc);
        for (ArrayList<NavigateNode> list : data) {
            Integer currentPathAllDistance = getCurrentPathAllDistance(list);//计算当前路径总距离
            System.out.println(currentPathAllDistance);
            System.out.println(list);
    private NavigateNode pythonObjTransferNode(Object obj, Integer z) {
        List<Integer> pathData = JSON.parseArray(obj.toString(), Integer.class);
        Integer x = pathData.get(0);
        Integer y = pathData.get(1);
        NavigateNode node = new NavigateNode(x, y);
        node.setDirection(null);
        node.setIsInflectionPoint(false);
        node.setZ(z);
        return node;
    }
    public Double similarityPath(List<NavigateNode> firstPath, List<NavigateNode> secondPath) {
        try {
            List<int[]> first = new ArrayList<>();
            for (NavigateNode node : firstPath) {
                first.add(new int[]{node.getX(), node.getY()});
            }
            List<int[]> second = new ArrayList<>();
            for (NavigateNode node : secondPath) {
                second.add(new int[]{node.getX(), node.getY()});
            }
            ProcessBuilder processBuilder = new ProcessBuilder("python", pythonCalcSimilarity, JSON.toJSONString(first), JSON.toJSONString(second));
            processBuilder.redirectErrorStream(true);
            Process process = processBuilder.start();
            // 读取Python脚本的输出
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            StringBuilder builder = new StringBuilder();
            while ((line = reader.readLine()) != null) {
                builder.append(line);
            }
            // 等待Python脚本执行完成
            int exitCode = process.waitFor();
            if (exitCode != 0) {
                System.out.println("Python script exited with error code: " + exitCode);
                return null;
            }
            reader.close();
            if (builder.length() <= 0) {
                return null;
            }
            PythonSimilarityResult result = JSON.parseObject(builder.toString(), PythonSimilarityResult.class);
            if (result.getCalcResult() != 200) {
                return 0D;
            }
            Double similarity = result.getSimilarity();
            return similarity;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0D;
    }
    public static void main(String[] args) {
//        //计算路径
//        List<NavigateNode> calc = calc("1000901", "1800201", NavigationMapType.NONE.id, null);
//        System.out.println(calc);
//        System.out.println("------------------------");
////        List<NavigateNode> calc = calc("0501401", "0201801", "out");
//        //将路径分割成多段
//        ArrayList<ArrayList<NavigateNode>> data = getSectionPath(calc);
//        for (ArrayList<NavigateNode> list : data) {
//            Integer currentPathAllDistance = getCurrentPathAllDistance(list);//计算当前路径总距离
//            System.out.println(currentPathAllDistance);
//            System.out.println(list);
//        }
        System.loadLibrary("example");
    }
src/main/java/com/zy/common/utils/News.java
File was deleted
src/main/java/com/zy/common/utils/NyHttpUtils.java
File was deleted
src/main/java/com/zy/common/utils/NyLiftUtils.java
File was deleted
src/main/java/com/zy/common/utils/NyShuttleOperaUtils.java
File was deleted
src/main/java/com/zy/common/utils/ShuttleOperaUtils.java
New file
@@ -0,0 +1,355 @@
package com.zy.common.utils;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.zy.asrs.entity.BasShuttle;
import com.zy.asrs.service.BasShuttleService;
import com.zy.asrs.utils.Utils;
import com.zy.common.model.NavigateNode;
import com.zy.core.News;
import com.zy.core.enums.ShuttleRunDirection;
import com.zy.core.model.command.ShuttleAssignCommand;
import com.zy.core.model.command.ShuttleCommand;
import com.zy.core.model.protocol.ShuttleProtocol;
import com.zy.core.thread.ShuttleThread;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
 * 四向车操作工具类
 * 此工具类只要作用于获取小车的各类命令List,移动命令、搬运货物命令、复位命令等。如命令为移动命令,还将返回行走路径List
 */
@Component
public class ShuttleOperaUtils {
    @Autowired
    private BasShuttleService basShuttleService;
    @Autowired
    private NavigateUtils navigateUtils;
    @Autowired
    private NavigateMapUtils navigateMapUtils;
    public synchronized List<ShuttleCommand> getStartToTargetCommands(String startLocNo, String endLocNo, Integer mapType, ShuttleAssignCommand assignCommand, ShuttleThread shuttleThread) {
        return getStartToTargetCommands(startLocNo, endLocNo, mapType, null, assignCommand, shuttleThread);
    }
    public synchronized List<ShuttleCommand> getStartToTargetCommands(String startLocNo, String endLocNo, Integer mapType, List<int[]> whites, ShuttleAssignCommand assignCommand, ShuttleThread shuttleThread) {
        ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
        if (shuttleProtocol == null) {
            return null;
        }
        Integer shuttleNo = shuttleProtocol.getShuttleNo();
        //获取小车移动速度
        Integer runSpeed = Optional.ofNullable(basShuttleService.selectOne(new EntityWrapper<BasShuttle>().eq("shuttle_no", shuttleNo)).getRunSpeed()).orElse(1000);
        List<NavigateNode> nodeList = navigateUtils.calc(startLocNo, endLocNo, mapType, Utils.getShuttlePoints(shuttleNo, Utils.getLev(startLocNo)), null);
        if (nodeList == null) {
            News.error("{} dash {} can't find navigate path!", startLocNo, endLocNo);
            return null;
        }
        List<NavigateNode> allNode = new ArrayList<>();
        for (NavigateNode node : nodeList) {
            allNode.add(node.clone());
        }
        List<ShuttleCommand> commands = new ArrayList<>();
        //获取分段路径
        ArrayList<ArrayList<NavigateNode>> data = navigateUtils.getSectionPath(nodeList);
        //将每一段路径分成command指令
        for (ArrayList<NavigateNode> nodes : data) {
            //开始路径
            NavigateNode startPath = nodes.get(0);
            //目标路径
            NavigateNode endPath = nodes.get(nodes.size() - 1);
            Integer allDistance = navigateUtils.getCurrentPathAllDistance(nodes);//计算当前路径行走总距离
            //通过xy坐标小车二维码
            String startCodeNum = NavigatePositionConvert.xyToPosition(startPath.getX(), startPath.getY(), startPath.getZ());
            //通过xy坐标小车二维码
            String distCodeNum = NavigatePositionConvert.xyToPosition(endPath.getX(), endPath.getY(), endPath.getZ());
            //获取移动命令
            ShuttleCommand command = shuttleThread.getMoveCommand(assignCommand.getDeviceTaskNo(), startCodeNum, distCodeNum, allDistance, ShuttleRunDirection.get(startPath.getDirection()).id.intValue(), runSpeed, nodes);
            command.setNodes(nodes);//将行走节点添加到每一步命令中
            commands.add(command);
        }
        assignCommand.setNodes(allNode);//当前任务所占用的节点list
        return commands;
    }
    public synchronized List<ShuttleCommand> shuttleInOutLiftCommand(String startLocNo, String endLocNo, Integer mapType, ShuttleAssignCommand assignCommand, ShuttleThread shuttleThread) {
        NavigateNode startNode = NavigatePositionConvert.locNoToNode(startLocNo);
        NavigateNode endNode = NavigatePositionConvert.locNoToNode(endLocNo);
        List<NavigateNode> unlockPath = new ArrayList<>();
        unlockPath.add(startNode);
        unlockPath.add(endNode);
        ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
        if (shuttleProtocol == null) {
            return null;
        }
        Integer shuttleNo = shuttleProtocol.getShuttleNo();
        //所使用的路径进行锁定/解锁
        boolean lockResult = navigateMapUtils.writeNavigateNodeToRedisMap(Utils.getLev(endLocNo), shuttleProtocol.getShuttleNo(), unlockPath, false);//所使用的路径进行解锁
        if (!lockResult) {
            News.error("{} dash {} can't find unlock path!", startLocNo, endLocNo);
            return null;//解锁失败
        }
        //获取小车移动速度
        Integer runSpeed = Optional.ofNullable(basShuttleService.selectOne(new EntityWrapper<BasShuttle>().eq("shuttle_no", shuttleNo)).getRunSpeed()).orElse(1000);
        List<NavigateNode> nodeList = navigateUtils.calc(startLocNo, endLocNo, mapType, Utils.getShuttlePoints(shuttleNo, Utils.getLev(startLocNo)), null);
        if (nodeList == null) {
            News.error("{} dash {} can't find navigate path!", startLocNo, endLocNo);
            return null;
        }
        List<NavigateNode> allNode = new ArrayList<>();
        for (NavigateNode node : nodeList) {
            allNode.add(node.clone());
        }
        List<ShuttleCommand> commands = new ArrayList<>();
        //获取分段路径
        ArrayList<ArrayList<NavigateNode>> data = navigateUtils.getSectionPath(nodeList);
        //将每一段路径分成command指令
        for (ArrayList<NavigateNode> nodes : data) {
            //开始路径
            NavigateNode startPath = nodes.get(0);
            //目标路径
            NavigateNode endPath = nodes.get(nodes.size() - 1);
            Integer allDistance = navigateUtils.getCurrentPathAllDistance(nodes);//计算当前路径行走总距离
            //通过xy坐标小车二维码
            String startCodeNum = NavigatePositionConvert.xyToPosition(startPath.getX(), startPath.getY(), startPath.getZ());
            //通过xy坐标小车二维码
            String distCodeNum = NavigatePositionConvert.xyToPosition(endPath.getX(), endPath.getY(), endPath.getZ());
            //获取移动命令
            ShuttleCommand command = shuttleThread.getMoveCommand(assignCommand.getDeviceTaskNo(), startCodeNum, distCodeNum, allDistance, ShuttleRunDirection.get(startPath.getDirection()).id.intValue(), runSpeed, nodes);
            command.setNodes(nodes);//将行走节点添加到每一步命令中
            commands.add(command);
        }
        assignCommand.setNodes(allNode);//当前任务所占用的节点list
        return commands;
    }
//    private boolean checkSimilarityPath(Motion motion, ShuttleAssignCommand assignCommand) {
//        String movePath = motion.getMovePath();
//        if (Cools.isEmpty(movePath)) {
//            return false;
//        }
//
//        Double similarityRef = 0.9D;
//        Dict similarityRefDict = dictService.getOne(new LambdaQueryWrapper<Dict>()
//                .eq(Dict::getFlag, "similarityRef")
//                .eq(Dict::getStatus, 1));
//        if (similarityRefDict != null) {
//            similarityRef = Double.parseDouble(similarityRefDict.getValue());
//        }
//
//        List<NavigateNode> originPath = JSON.parseArray(movePath, NavigateNode.class);
//        List<NavigateNode> finalPath = assignCommand.getNodes();
//
//        if (finalPath == null) {
//            return false;
//        }
//
//        Double similarity = navigateUtils.similarityPath(originPath, finalPath);
//        if (similarity <= similarityRef) {
//            Object object = redisUtil.get(DeviceRedisConstant.SIMILARITY_TIMES + motion.getTaskNo());
//            if (object == null) {
//                redisUtil.set(DeviceRedisConstant.SIMILARITY_TIMES + motion.getTaskNo(), System.currentTimeMillis(), 60 * 60 * 24);
//            }else {
//                long similarityTimeoutRef = 20L;//默认超时20s
//                Dict similarityTimeoutDict = dictService.getOne(new LambdaQueryWrapper<Dict>()
//                        .eq(Dict::getFlag, "similarityTimeout")
//                        .eq(Dict::getStatus, 1));
//                if (similarityTimeoutDict != null) {
//                    similarityTimeoutRef = Long.parseLong(similarityTimeoutDict.getValue());
//                }
//
//                long recordTime = Long.parseLong(object.toString());
//                if (System.currentTimeMillis() - recordTime > (60 * similarityTimeoutRef)) {
//                    //超时,直接放行
//                    return true;
//                }
//            }
//            News.error("{} dash {} path similarity mismatch!", motion.getOrigin(), motion.getTarget());
//            return false;
//        }
//
//        return true;
//    }
//    /**
//     * 计算并获取小车从起点——中间点——目标点之间搬运货物动作命令
//     * @param shuttleNo 小车号
//     * @param wrkNo 工作号
//     * @param startPoint 起点(小车当前位置)
//     * @param targetPoint 目标点(货物目标位置)
//     */
//    public static synchronized ShuttleOperaResult getShuttleTransportCommands(Integer shuttleNo, Integer wrkNo, String startPoint, String targetPoint) {
//        //行走路径
//        ArrayList<NavigateNode> nodes = new ArrayList<>();
//        //命令集合
//        ArrayList<NyShuttleHttpCommand> commands = new ArrayList<>();
//
//        //计算起点到目标点命令
//        ShuttleOperaResult result = getStartToTargetCommands(shuttleNo, wrkNo, startPoint, targetPoint, NavigationMapType.DFX.id);
//        if (result == null) {
//            //计算结果必须不为空,否则计算失败
//            return null;
//        }
//        nodes.addAll(result.getNodes());
//        //起点位置下发一条顶升命令将货物进行搬运
//        commands.add(NyHttpUtils.getPalletLiftCommand(shuttleNo, wrkNo, true));
//        commands.addAll(result.getCommands());//起点到目标点移动命令
//        //当小车行走到目标点后,需要下发一条下降命令将货物放置
//        commands.add(NyHttpUtils.getPalletLiftCommand(shuttleNo, wrkNo, false));
//        return result(commands, nodes);
//    }
//
//    /**
//     * 计算并获取小车从起点——中间点——目标点之间搬运货物动作命令
//     * @param shuttleNo 小车号
//     * @param wrkNo 工作号
//     * @param startPoint 起点(小车当前位置)
//     * @param middlePoint 中间点(货物位置)
//     * @param targetPoint 目标点(货物目标位置)
//     */
//    public static synchronized ShuttleOperaResult getShuttleTransportCommands(Integer shuttleNo, Integer wrkNo, String startPoint, String middlePoint, String targetPoint) {
//        //行走路径
//        ArrayList<NavigateNode> nodes = new ArrayList<>();
//        //命令集合
//        ArrayList<NyShuttleHttpCommand> commands = new ArrayList<>();
//
//        if (!startPoint.equals(middlePoint)) {//起点和中间点不一致,需要计算起点到中间点路径
//            //计算起点到中间点命令
//            ShuttleOperaResult result1 = getStartToTargetCommands(shuttleNo, wrkNo, startPoint, middlePoint, NavigationMapType.NORMAL.id);
//            if (result1 == null) {
//                //计算结果必须不为空,否则计算失败
//                return null;
//            }
//            nodes.addAll(result1.getNodes());
//            commands.addAll(result1.getCommands());
//        }
//
//        //计算中间点到目标点命令
//        ShuttleOperaResult result2 = getStartToTargetCommands(shuttleNo, wrkNo, middlePoint, targetPoint, NavigationMapType.DFX.id);
//        if (result2 == null) {
//            //计算结果必须不为空,否则计算失败
//            return null;
//        }
//        nodes.addAll(result2.getNodes());
//        //当小车行走到中间点后,需要下发一条顶升命令将货物进行搬运
//        commands.add(NyHttpUtils.getPalletLiftCommand(shuttleNo, wrkNo, true));
//        commands.addAll(result2.getCommands());//中间点到目标点移动命令
//        //当小车行走到目标点后,需要下发一条下降命令将货物放置
//        commands.add(NyHttpUtils.getPalletLiftCommand(shuttleNo, wrkNo, false));
//        return result(commands, nodes);
//    }
//
//    /**
//     * 获取起点到目标点行走命令
//     */
//    public synchronized ShuttleOperaResult getStartToTargetCommands(Integer shuttleNo, Integer wrkNo, String startPoint, String targetPoint, Integer mapType) {
//        NavigateMapUtils navigateMapUtils = SpringUtils.getBean(NavigateMapUtils.class);
//        //计算起点到目标点行走节点
//        List<NavigateNode> calc = NavigateUtils.calc(startPoint, targetPoint, mapType, Utils.getShuttlePoints(shuttleNo, Utils.getLev(startPoint)), null);
//        if (calc == null) {
//            return null;
//        }
//
//        //命令集合
//        ArrayList<NyShuttleHttpCommand> commands = new ArrayList<>();
//        List<NavigateNode> allNode = new ArrayList<>();
//
//        //获取分段路径
//        ArrayList<ArrayList<NavigateNode>> data = NavigateUtils.getSectionPath(calc);
//        //将每一段路径分成command指令
//        for (ArrayList<NavigateNode> nodes : data) {
//            //开始路径
//            NavigateNode startPath = nodes.get(0);
//            //目标路径
//            NavigateNode targetPath = nodes.get(nodes.size() - 1);
//            //获取移动命令
//            NyShuttleHttpCommand moveCommand = NyHttpUtils.getMoveCommand(shuttleNo, wrkNo, startPath, targetPath);
//            moveCommand.setNodes(nodes);//将行走节点添加到每一步命令中
//            commands.add(moveCommand);
//
//            allNode.addAll(nodes);
//        }
//
//        boolean result = navigateMapUtils.writeNavigateNodeToRedisMap(Utils.getLev(startPoint), shuttleNo, allNode, true);//锁定路径
//        if (!result) {
//            return null;//路径锁定失败
//        }
//        return result(commands, calc);
//    }
//
//    /**
//     * 获取起点到目标点行走命令(可传白名单)
//     */
//    public static synchronized ShuttleOperaResult getStartToTargetCommandsByWhites(Integer shuttleNo, Integer wrkNo, String startPoint, String targetPoint, Integer mapType, List<int[]> whites) {
//        NavigateMapUtils navigateMapUtils = SpringUtils.getBean(NavigateMapUtils.class);
//        //计算起点到目标点行走节点
//        List<NavigateNode> calc = NavigateUtils.calc(startPoint, targetPoint, mapType, Utils.getShuttlePoints(shuttleNo, Utils.getLev(startPoint)), whites);
//        if (calc == null) {
//            return null;
//        }
//
//        //命令集合
//        ArrayList<NyShuttleHttpCommand> commands = new ArrayList<>();
//        List<NavigateNode> allNode = new ArrayList<>();
//
//        //获取分段路径
//        ArrayList<ArrayList<NavigateNode>> data = NavigateUtils.getSectionPath(calc);
//        //将每一段路径分成command指令
//        for (ArrayList<NavigateNode> nodes : data) {
//            //开始路径
//            NavigateNode startPath = nodes.get(0);
//            //目标路径
//            NavigateNode targetPath = nodes.get(nodes.size() - 1);
//            //获取移动命令
//            NyShuttleHttpCommand moveCommand = NyHttpUtils.getMoveCommand(shuttleNo, wrkNo, startPath, targetPath);
//            moveCommand.setNodes(nodes);//将行走节点添加到每一步命令中
//            commands.add(moveCommand);
//
//            allNode.addAll(nodes);
//        }
//
//        //锁定路径时剔除白名单节点
//        ArrayList<NavigateNode> nodes = new ArrayList<>();
//        for (NavigateNode node : allNode) {
//            boolean flag = false;
//            for (int[] white : whites) {
//                if (node.getX() == white[0] && node.getY() == white[1]) {
//                    flag = true;//存在白名单节点
//                    break;//跳过白名单节点
//                }
//            }
//
//            if (!flag) {
//                nodes.add(node);
//            }
//        }
//        boolean result = navigateMapUtils.writeNavigateNodeToRedisMap(Utils.getLev(startPoint), shuttleNo, nodes, true);//锁定路径
//        if (!result) {
//            return null;//路径锁定失败
//        }
//        return result(commands, calc);
//    }
//
//    //返回结果集
//    public static ShuttleOperaResult result(List<NyShuttleHttpCommand> commands, List<NavigateNode> nodes) {
//        return new ShuttleOperaResult(commands, nodes);
//    }
}
src/main/java/com/zy/core/CrnThread.java
File was deleted
src/main/java/com/zy/core/MainProcess.java
@@ -41,43 +41,41 @@
                        continue;
                    }
                    // 入库  ===>> 入库站到堆垛机站,根据条码扫描生成入库工作档
                    mainService.generateStoreWrkFile(); // 组托
//                    // 入库  ===>> 入库站到堆垛机站,根据条码扫描生成入库工作档
//                    mainService.generateStoreWrkFile(); // 组托
                    //初始化实时地图
                    mainService.initRealtimeBasMap();
                    // 拣料、并板再入库
                    mainService.stnToCrnStnPick();
                    // 盘点再入库
                    mainService.stnToCrnStnPlate();
                    // 入库  ===>>  四向穿梭车入库作业下发
                    mainService.shuttleInExecute();
                    // 出库  ===>>  四向穿梭车出库作业下发
                    mainService.shuttleOutExecute();
                    //四向穿梭车任务完成
                    mainService.shuttleFinished();
                    //提升机任务
                    mainService.liftIoExecute();
                    //提升机任务完成
                    mainService.liftFinished();
                    //库位移转
                    mainService.locToLocExecute();
//                    // 拣料、并板再入库
//                    mainService.stnToCrnStnPick();
//                    // 盘点再入库
//                    mainService.stnToCrnStnPlate();
//                    // 入库  ===>>  四向穿梭车入库作业下发
//                    mainService.shuttleInExecute();
//                    // 出库  ===>>  四向穿梭车出库作业下发
//                    mainService.shuttleOutExecute();
//                    //四向穿梭车任务完成
//                    mainService.shuttleFinished();
//                    //提升机任务
//                    mainService.liftIoExecute();
//                    //提升机任务完成
//                    mainService.liftFinished();
                    //执行小车移库任务
                    mainService.shuttleMoveExecute();
                    // 异常信息记录
                    mainService.recErr();
                    // 入库  ===>> 空栈板初始化入库,叉车入库站放货
                    mainService.storeEmptyPlt();
                    // 出库  ===>> 工作档信息写入led显示器
                    mainService.ledExecute();
                    // 其他  ===>> LED显示器复位,显示默认信息
                    mainService.ledReset();
                    // 穿梭车 ===>> 小车电量检测充电
                    mainService.loopShuttleCharge();
                    mainService.executeShuttleCharge();
//                    // 异常信息记录
//                    mainService.recErr();
//                    // 入库  ===>> 空栈板初始化入库,叉车入库站放货
//                    mainService.storeEmptyPlt();
//                    // 出库  ===>> 工作档信息写入led显示器
//                    mainService.ledExecute();
//                    // 其他  ===>> LED显示器复位,显示默认信息
//                    mainService.ledReset();
//                    // 穿梭车 ===>> 小车电量检测充电
//                    mainService.loopShuttleCharge();
//                    mainService.executeShuttleCharge();
                    //扫描设备PakMk标记是否超时
                    mainService.scanDevicePakMk();
//                    //扫描设备PakMk标记是否超时
//                    mainService.scanDevicePakMk();
                    // 间隔
                    Thread.sleep(200);
src/main/java/com/zy/core/ServerBootstrap.java
@@ -7,6 +7,8 @@
import com.zy.core.model.*;
import com.zy.core.properties.SlaveProperties;
import com.zy.core.thread.*;
import com.zy.core.thread.impl.NyShuttleThread;
import com.zy.core.thread.impl.ZyForkLiftThread;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
@@ -49,12 +51,6 @@
        for (Slave devp : slaveProperties.getDevp()) {
            MessageQueue.init(SlaveType.Devp, devp);
        }
        for (Slave devp2 : slaveProperties.getDevp2()) {
            MessageQueue.init(SlaveType.Devp2, devp2);
        }
        for (Slave devp3 : slaveProperties.getDevp3()) {
            MessageQueue.init(SlaveType.Devp3, devp3);
        }
        // 初始化条码扫描仪mq
        for (Slave barcode : slaveProperties.getBarcode()) {
            MessageQueue.init(SlaveType.Barcode, barcode);
@@ -71,9 +67,9 @@
        for (Slave car : slaveProperties.getCar()) {
            MessageQueue.init(SlaveType.Car, car);
        }
        // 初始化提升机mq
        for (Slave lift : slaveProperties.getLift()) {
            MessageQueue.init(SlaveType.Lift, lift);
        // 初始化货叉提升机mq
        for (Slave forkLift : slaveProperties.getForkLift()) {
            MessageQueue.init(SlaveType.ForkLift, forkLift);
        }
        // 初始化四向穿梭车mq
        for (Slave shuttle : slaveProperties.getShuttle()) {
@@ -89,12 +85,12 @@
            new Thread((Runnable) devpThread).start();
            SlaveConnection.put(SlaveType.Devp, devp.getId(), devpThread);
        }
        // 初始化提升机
        News.info("初始化提升机........................................................");
        for (LiftSlave liftSlave : slaveProperties.getLift()) {
            LiftThread liftThread = new LiftThread(liftSlave, redisUtil);
            new Thread(liftThread).start();
            SlaveConnection.put(SlaveType.Lift, liftSlave.getId(), liftThread);
        // 初始化货叉提升机
        News.info("初始化货叉提升机........................................................");
        for (ForkLiftSlave forkLiftSlave : slaveProperties.getForkLift()) {
            ZyForkLiftThread forkLiftThread = new ZyForkLiftThread(forkLiftSlave, redisUtil);
            new Thread(forkLiftThread).start();
            SlaveConnection.put(SlaveType.ForkLift, forkLiftSlave.getId(), forkLiftThread);
        }
        // 初始化四向穿梭车
        News.info("初始化四向穿梭车......................................................");
src/main/java/com/zy/core/ThreadHandler.java
@@ -1,9 +1,10 @@
package com.zy.core;
public interface ThreadHandler {
public interface ThreadHandler extends Runnable {
    boolean connect();
    void close();
}
src/main/java/com/zy/core/action/ForkLiftAction.java
New file
@@ -0,0 +1,155 @@
package com.zy.core.action;
import com.alibaba.fastjson.JSON;
import com.zy.asrs.entity.BasLiftOpt;
import com.zy.asrs.entity.WrkMast;
import com.zy.asrs.service.BasLiftOptService;
import com.zy.asrs.service.WrkMastService;
import com.zy.common.utils.RedisUtil;
import com.zy.core.News;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.ForkLiftTaskModeType;
import com.zy.core.enums.RedisKeyType;
import com.zy.core.enums.SlaveType;
import com.zy.core.model.CommandResponse;
import com.zy.core.model.command.ForkLiftCommand;
import com.zy.core.model.command.LiftAssignCommand;
import com.zy.core.model.command.LiftRedisCommand;
import com.zy.core.model.protocol.ForkLiftProtocol;
import com.zy.core.thread.ForkLiftThread;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
@Component
public class ForkLiftAction {
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private WrkMastService wrkMastService;
    @Autowired
    private BasLiftOptService basLiftOptService;
    public synchronized boolean assignWork(Integer liftNo, LiftAssignCommand assignCommand) {
        ForkLiftThread forkLiftThread = (ForkLiftThread) SlaveConnection.get(SlaveType.ForkLift, liftNo);
        if (forkLiftThread == null) {
            return false;
        }
        ForkLiftProtocol forkLiftProtocol = forkLiftThread.getStatus();
        if (forkLiftProtocol == null) {
            return false;
        }
        LiftRedisCommand redisCommand = new LiftRedisCommand();
        redisCommand.setLiftNo(assignCommand.getLiftNo());//提升机号
        redisCommand.setWrkNo(assignCommand.getTaskNo());//工作号
        redisCommand.setCommandStep(0);//命令执行步序
        redisCommand.setAssignCommand(assignCommand);//命令
        //任务数据保存到redis
        if (redisUtil.set(RedisKeyType.FORK_LIFT.key + assignCommand.getTaskNo(), JSON.toJSONString(redisCommand))) {
            forkLiftThread.setSyncTaskNo(assignCommand.getTaskNo().intValue());
            return true;
        }
        return false;
    }
    public synchronized boolean executeWork(Integer liftNo, Integer taskNo) {
        Object obj = redisUtil.get(RedisKeyType.FORK_LIFT.key + taskNo);
        if (obj == null) {
            return false;
        }
        WrkMast wrkMast = wrkMastService.selectByWorkNo(taskNo);
        if (wrkMast == null) {
            return false;
        }
        LiftRedisCommand redisCommand = JSON.parseObject(obj.toString(), LiftRedisCommand.class);
        if (redisCommand == null) {
            return false;
        }
        ForkLiftThread forkLiftThread = (ForkLiftThread) SlaveConnection.get(SlaveType.ForkLift, liftNo);
        if (forkLiftThread == null) {
            return false;
        }
        ForkLiftProtocol forkLiftProtocol = forkLiftThread.getStatus();
        if (forkLiftProtocol == null) {
            return false;
        }
        List<ForkLiftCommand> commands = redisCommand.getAssignCommand().getCommands();
        if (commands.isEmpty()) {
            return false;
        }
        LiftAssignCommand assignCommand = redisCommand.getAssignCommand();
        int commandStep = redisCommand.getCommandStep();
        if (commandStep == 0) {
            //取出命令
            ForkLiftCommand command = commands.get(commandStep);
            //判断提升机是否空闲
            if (!forkLiftThread.isIdle()) {
                return false;
            }
            // 下发命令
            CommandResponse response = write(command, liftNo);
            //保存命令日志
            BasLiftOpt basLiftOpt = new BasLiftOpt();
            basLiftOpt.setWrkNo(taskNo);
            basLiftOpt.setLiftNo(liftNo);
            basLiftOpt.setCommand(JSON.toJSONString(command));
            basLiftOpt.setSystemStatus(JSON.toJSONString(forkLiftProtocol));
            basLiftOpt.setDeviceWrk(String.valueOf(command.getTaskNo()));
            basLiftOpt.setSendTime(new Date());//指令下发时间
            //保存命令流水
            basLiftOptService.insert(basLiftOpt);
            if (!response.getResult()) {
                News.error("货叉提升机命令下发失败,提升机号={},任务数据={}", command.getLiftNo(), JSON.toJSON(command));
                return false;
            } else {
                News.info("货叉提升机命令下发成功,提升机号={},任务数据={}", command.getLiftNo(), JSON.toJSON(command));
            }
            commandStep++;
            //更新redis数据
            redisCommand.setCommandStep(commandStep);
            // 更新redis数据
            redisUtil.set(RedisKeyType.FORK_LIFT.key + taskNo, JSON.toJSONString(redisCommand));
        }
        return true;
    }
    private synchronized CommandResponse write(ForkLiftCommand command, Integer liftNo) {
        CommandResponse response = new CommandResponse(false);
        if (null == command) {
            News.error("提升机写入命令为空");
            response.setMessage("提升机写入命令为空");
            return response;
        }
        ForkLiftThread forkLiftThread = (ForkLiftThread) SlaveConnection.get(SlaveType.ForkLift, liftNo);
        if (forkLiftThread == null) {
            return response;
        }
        if (command.getMode().intValue() == ForkLiftTaskModeType.PICK_PUT.id) {
            response = forkLiftThread.pickAndPut(command);
        } else if (command.getMode().intValue() == ForkLiftTaskModeType.SHUTTLE_SWITCH.id) {
            response = forkLiftThread.shuttleSwitch(command);
        }
        return response;
    }
}
src/main/java/com/zy/core/action/ShuttleAction.java
New file
@@ -0,0 +1,668 @@
package com.zy.core.action;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zy.asrs.entity.BasShuttleOpt;
import com.zy.asrs.service.BasShuttleOptService;
import com.zy.asrs.service.BasShuttleService;
import com.zy.asrs.service.LocMastService;
import com.zy.asrs.utils.Utils;
import com.zy.common.ExecuteSupport;
import com.zy.common.model.NavigateNode;
import com.zy.common.utils.NavigateMapUtils;
import com.zy.common.utils.RedisUtil;
import com.zy.core.News;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.*;
import com.zy.core.model.CommandResponse;
import com.zy.core.model.command.ShuttleAssignCommand;
import com.zy.core.model.command.ShuttleCommand;
import com.zy.core.model.command.ShuttleRedisCommand;
import com.zy.core.model.protocol.ShuttleProtocol;
import com.zy.core.thread.ShuttleThread;
import com.zy.system.service.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.Date;
import java.util.List;
@Component
public class ShuttleAction {
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private NavigateMapUtils navigateMapUtils;
    @Autowired
    private BasShuttleService basShuttleService;
    @Autowired
    private LocMastService locMastService;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private ConfigService configService;
    @Autowired
    private BasShuttleOptService basShuttleOptService;
    public synchronized boolean assignWork(Integer shuttleNo, ShuttleAssignCommand assignCommand) {
        ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
        if (shuttleThread == null) {
            return false;
        }
        ShuttleRedisCommand redisCommand = new ShuttleRedisCommand();
        redisCommand.setShuttleNo(assignCommand.getShuttleNo());//四向穿梭车号
        redisCommand.setWrkNo(assignCommand.getTaskNo());//工作号
        redisCommand.setCommandStep(0);//命令执行步序
        redisCommand.setAssignCommand(assignCommand);//命令
        //任务数据保存到redis
        if (redisUtil.set(RedisKeyType.SHUTTLE.key + assignCommand.getTaskNo(), JSON.toJSONString(redisCommand, SerializerFeature.DisableCircularReferenceDetect))) {
            shuttleThread.setSyncTaskNo(assignCommand.getTaskNo());
            return true;
        }
        return false;
    }
    public synchronized boolean executeWork(Integer shuttleNo, Integer taskNo) {
        Object obj = redisUtil.get(RedisKeyType.SHUTTLE.key + taskNo);
        if (obj == null) {
            return false;
        }
        ShuttleRedisCommand redisCommand = null;
        try {
            redisCommand = objectMapper.readValue(String.valueOf(obj), ShuttleRedisCommand.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        if (redisCommand == null) {
            return false;
        }
        ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
        if (shuttleThread == null) {
            return false;
        }
        ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
        if (shuttleProtocol == null) {
            return false;
        }
        //判断工作号是否相同
        if (!shuttleProtocol.getTaskNo().equals(taskNo)) {
            return false;
        }
        List<ShuttleCommand> commands = redisCommand.getAssignCommand().getCommands();
        if (commands.isEmpty()) {
            return false;
        }
        ShuttleAssignCommand assignCommand = redisCommand.getAssignCommand();
        int commandStep = redisCommand.getCommandStep();
        Integer mode = -1;
        if(commandStep < commands.size()) {
            //取出命令
            ShuttleCommand currentCommand = commands.get(commandStep);
            mode = currentCommand.getMode();
        }
        //判断设备是否空闲
        Integer finalMode = mode;
        if (!shuttleThread.isDeviceIdle(new ExecuteSupport() {
            @Override
            public Boolean judgement() {
                if (ShuttleCommandModeType.CHARGE_CLOSE.id.equals(finalMode)) {//关闭充电
                    return false;//不需要判断状态
                }
                return true;//需要判断状态
            }
        })) {
            return false;
        }
        // 完结上一条命令
        boolean updateCommand = false;
        if (commandStep != 0) {
            ShuttleCommand command = commands.get(commandStep - 1);
            if (command.getMode() == ShuttleCommandModeType.MOVE.id) {
                // 正常移动
                if (command.getTargetLocNo().equals(shuttleProtocol.getCurrentLocNo())) {
                    command.setComplete(true);
                    updateCommand = true;
                    //解锁锁定路径,上一条路径
                    List<NavigateNode> nodes = null;
                    try {
                        String nodesStr = objectMapper.writeValueAsString(command.getNodes());
                        nodes = objectMapper.readValue(nodesStr, new TypeReference<List<NavigateNode>>() {
                        });
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                    if (nodes != null) {
                        NavigateNode targetNode = assignCommand.getNodes().get(assignCommand.getNodes().size() - 1);//最终节点
                        NavigateNode node = nodes.get(nodes.size() - 1);
                        if (!(targetNode.getX() == node.getX() && targetNode.getY() == node.getY())) {
                            nodes.remove(nodes.size() - 1);//剔除尾节点
                        }
                        boolean result = navigateMapUtils.writeNavigateNodeToRedisMap(Utils.getLev(shuttleProtocol.getCurrentLocNo()), shuttleProtocol.getShuttleNo(), nodes, false);//解锁路径
                        if (!result) {
                            return false;//解锁失败
                        }
                    }
                }
            } else if (command.getMode() == ShuttleCommandModeType.PALLET_LIFT.id) {
                // 托盘顶升
                //判断是否顶升到位
                if (shuttleProtocol.getHasLift()) {
                    command.setComplete(true);
                    updateCommand = true;
//                    //判断是否有物
//                    if (shuttleProtocol.getHasPallet()) {
//                        command.setComplete(true);
//                    }
                }
            } else if (command.getMode() == ShuttleCommandModeType.PALLET_DOWN.id) {
                // 托盘下降命令
                // 判断是否下降到位
                if (!shuttleProtocol.getHasLift()) {
                    command.setComplete(true);
                    updateCommand = true;
                }
            } else if (command.getMode() == ShuttleCommandModeType.CHARGE_OPEN.id) {
                // 充电开
                //判断小车充电状态
                if (shuttleProtocol.getHasCharge()) {
                    command.setComplete(true);
                    updateCommand = true;
                }
            }else {
                command.setComplete(true);//其他命令默认认为完成
                updateCommand = true;
            }
            if(updateCommand) {
                // 更新redis数据
                redisUtil.set(RedisKeyType.SHUTTLE.key + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand, SerializerFeature.DisableCircularReferenceDetect));
            }
            if (!command.getComplete()) {
                return false;
            }
            //判断是否为最后一条命令且命令执行完成,抛出等待确认状态
            ShuttleCommand endCommand = commands.get(commands.size() - 1);
            if (endCommand.getComplete()) {
                News.info("四向穿梭车任务执行下发完成等待执行结束,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(commands));
                // 系统任务
                if (assignCommand.getAuto()) {
                    if (!assignCommand.getCharge()) {
                        //对主线程抛出等待确认状态waiting
                        shuttleThread.setProtocolStatus(ShuttleProtocolStatusType.WAITING);
                    }else {
                        shuttleThread.setProtocolStatus(ShuttleProtocolStatusType.CHARGING_WAITING);
                    }
                    News.info("四向穿梭车任务执行下发完成等待执行结束,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
                    // 手动任务
                } else {
                    //手动模式不抛出等待状态,直接复位空闲状态
                    shuttleThread.setProtocolStatus(ShuttleProtocolStatusType.IDLE);
                    //任务号清零
                    shuttleThread.setSyncTaskNo(0);
                    //标记复位
                    shuttleThread.setPakMk(true);
                    News.info("四向穿梭车手动任务执行完成,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
                }
                //删除redis
                redisUtil.del(RedisKeyType.SHUTTLE.key + redisCommand.getWrkNo());
                return false;//禁止再下发命令
            }
        }
        //取出命令
        ShuttleCommand command = commands.get(commandStep);
        // 下发命令
        CommandResponse response = write(command, shuttleNo);
        //保存命令日志
        BasShuttleOpt basShuttleOpt = new BasShuttleOpt();
        basShuttleOpt.setWrkNo(redisCommand.getWrkNo());
        basShuttleOpt.setShuttleNo(shuttleNo);
        basShuttleOpt.setMode(ShuttleTaskModeType.get(assignCommand.getTaskMode()).desc);
        basShuttleOpt.setSourceLocNo(assignCommand.getSourceLocNo());
        basShuttleOpt.setDistLocNo(assignCommand.getLocNo());
        basShuttleOpt.setCommand(JSON.toJSONString(command));
        basShuttleOpt.setSystemStatus(JSON.toJSONString(shuttleProtocol));
        basShuttleOpt.setDeviceWrk(String.valueOf(command.getTaskNo()));
        basShuttleOpt.setResponse(response.getMessage());//获取响应
        basShuttleOpt.setSendTime(new Date());//指令下发时间
        basShuttleOpt.setSend(response.getResult() ? 1 : 0);
        //保存命令流水
        basShuttleOptService.insert(basShuttleOpt);
        if (!response.getResult()) {
            News.error("四向穿梭车命令下发失败,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
            return false;
        }
        shuttleThread.setProtocolStatus(ShuttleProtocolStatusType.WORKING);
        commandStep++;
        //更新redis数据
        redisCommand.setCommandStep(commandStep);
        //任务数据保存到redis
        redisUtil.set(RedisKeyType.SHUTTLE.key + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand));
        return true;
    }
//    //跑库程序
//    public synchronized void moveLoc(Integer shuttleNo) {
//        ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
//        if (shuttleThread == null) {
//            return;
//        }
//        ShuttleProtocol shuttleProtocol = shuttleThread.getStatus(false);
//        if (shuttleProtocol == null) {
//            return;
//        }
//
//        //小车开启跑库模式
//        if (!shuttleProtocol.getMoveLoc()) {
//            return;
//        }
//
//        //小车空闲
//        if (!shuttleThread.isIdle()) {
//            return;
//        }
//
//        int lev = Utils.getLev(shuttleProtocol.getCurrentLocNo());//小车当前楼层
//
//        if (shuttleProtocol.getMoveType() == 0) {//跑轨道
//            //根据地图方向决定跑x或y
//            Config config = configService.selectOne(new EntityWrapper<Config>()
//                    .eq("code", "direction_map")
//                    .eq("status", 1));
//            if (config == null) {
//                //跑库结束
//                shuttleProtocol.setMoveLoc(false);
//                shuttleProtocol.setMoveType(0);
//                shuttleProtocol.setXStart(0);
//                shuttleProtocol.setXTarget(0);
//                shuttleProtocol.setXCurrent(0);
//                shuttleProtocol.setYStart(0);
//                shuttleProtocol.setYTarget(0);
//                shuttleProtocol.setYCurrent(0);
//                return;
//            }
//            String direction = config.getValue();
//
//            if (direction.equals("y")) {//跑x轴方向,跑完x轴再切换y轴
//                ArrayList<String> locs = new ArrayList<>();
//                for (int i = shuttleProtocol.getXCurrent(); i <= shuttleProtocol.getXTarget(); i++) {
//                    String locNo = Utils.getLocNo(i, shuttleProtocol.getYCurrent(), lev);
//                    locs.add(locNo);
//                }
//
//                List<LocMast> locList = locMastService.selectList(new EntityWrapper<LocMast>()
//                        .eq("loc_sts", LocStsType.O.toString())
//                        .in("loc_no", locs));
//                if (locList.isEmpty()) {
//                    //空库位
//                    shuttleProtocol.setYCurrent(shuttleProtocol.getYCurrent() + 1);
//                    return;
//                }
//
//                LocMast start = locList.get(0);
//                LocMast target = locList.get(locList.size() - 1);
//                //判断小车是否在起点位置
//                if (!shuttleProtocol.getCurrentLocNo().equals(start.getLocNo())) {//不在起点位置,调度去起点位置
//                    shuttleDispatcher.generateMoveTask(device, start.getLocNo());
//                }else {
//                    //在起点位置,调度去目标位置
//                    Task task = shuttleDispatcher.generateMoveTask(device, target.getLocNo());
//                    if (task != null) {
//                        shuttleProtocol.setYCurrent(shuttleProtocol.getYCurrent() + 1);//切换y轴
//                    }
//
//                    if(shuttleProtocol.getYCurrent() > shuttleProtocol.getYTarget()) {
//                        //y轴也跑完了,结束跑库
//                        shuttleProtocol.setMoveLoc(false);
//                        shuttleProtocol.setMoveType(0);
//                        shuttleProtocol.setXStart(0);
//                        shuttleProtocol.setXTarget(0);
//                        shuttleProtocol.setXCurrent(0);
//                        shuttleProtocol.setYStart(0);
//                        shuttleProtocol.setYTarget(0);
//                        shuttleProtocol.setYCurrent(0);
//                        return;
//                    }
//                }
//            }else {//跑y轴方向,跑完y轴再切换x轴
//                ArrayList<String> locs = new ArrayList<>();
//                for (int i = shuttleProtocol.getYCurrent(); i <= shuttleProtocol.getYTarget(); i++) {
//                    String locNo = Utils.getLocNo(shuttleProtocol.getXCurrent(), i, lev);
//                    locs.add(locNo);
//                }
//
//                List<Loc> locList = locService.list(new LambdaQueryWrapper<Loc>()
//                        .eq(Loc::getLocSts, LocStsType.O.val())
//                        .in(Loc::getLocNo, locs));
//                if (locList.isEmpty()) {
//                    //空库位
//                    shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);
//                    return;
//                }
//
//                Loc start = locList.get(0);
//                Loc target = locList.get(locList.size() - 1);
//                //判断小车是否在起点位置
//                if (!shuttleProtocol.getCurrentLocNo().equals(start.getLocNo())) {//不在起点位置,调度去起点位置
//                    shuttleDispatcher.generateMoveTask(device, start.getLocNo());
//                }else {
//                    //在起点位置,调度去目标位置
//                    Task task = shuttleDispatcher.generateMoveTask(device, target.getLocNo());
//                    if (task != null) {
//                        shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);//切换x轴
//                    }
//
//                    if(shuttleProtocol.getXCurrent() > shuttleProtocol.getXTarget()) {
//                        //y轴也跑完了,结束跑库
//                        shuttleProtocol.setMoveLoc(false);
//                        shuttleProtocol.setMoveType(0);
//                        shuttleProtocol.setXStart(0);
//                        shuttleProtocol.setXTarget(0);
//                        shuttleProtocol.setXCurrent(0);
//                        shuttleProtocol.setYStart(0);
//                        shuttleProtocol.setYTarget(0);
//                        shuttleProtocol.setYCurrent(0);
//                        return;
//                    }
//                }
//            }
//
//        } else if (shuttleProtocol.getMoveType() == 1) {//跑库位
//            //根据地图方向决定跑x或y
//            Dict dict = dictService.getOne(new LambdaQueryWrapper<Dict>()
//                    .eq(Dict::getFlag, "direction_map")
//                    .eq(Dict::getStatus, 1));
//            if (dict == null) {
//                //跑库结束
//                shuttleProtocol.setMoveLoc(false);
//                shuttleProtocol.setMoveType(0);
//                shuttleProtocol.setXStart(0);
//                shuttleProtocol.setXTarget(0);
//                shuttleProtocol.setXCurrent(0);
//                shuttleProtocol.setYStart(0);
//                shuttleProtocol.setYTarget(0);
//                shuttleProtocol.setYCurrent(0);
//                return;
//            }
//            String direction = dict.getValue();
//
//            if (direction.equals("y")) {//跑x轴方向,跑完x轴再切换y轴
//                Integer xCurrent = shuttleProtocol.getXCurrent();
//
//                //获取待跑库位号
//                String locNo = Utils.getLocNo(xCurrent, shuttleProtocol.getYCurrent(), lev);
//                Loc target = locService.getOne(new LambdaQueryWrapper<Loc>()
//                        .eq(Loc::getLocNo, locNo)
//                        .eq(Loc::getLocSts, LocStsType.O.val())
//                        .eq(Loc::getHostId, device.getHostId()));
//                if (target == null || shuttleProtocol.getCurrentLocNo().equals(locNo)) {//库位不存在或小车已在当前位置
//                    shuttleProtocol.setXCurrent(xCurrent + 1);
//                    if (shuttleProtocol.getXCurrent() > shuttleProtocol.getXTarget()) {
//                        //x轴跑完,切换y轴
//                        shuttleProtocol.setXCurrent(shuttleProtocol.getXStart());
//                        shuttleProtocol.setYCurrent(shuttleProtocol.getYCurrent() + 1);
//
//                        if(shuttleProtocol.getYCurrent() > shuttleProtocol.getYTarget()) {
//                            //y轴也跑完了,结束跑库
//                            shuttleProtocol.setMoveLoc(false);
//                            shuttleProtocol.setMoveType(0);
//                            shuttleProtocol.setXStart(0);
//                            shuttleProtocol.setXTarget(0);
//                            shuttleProtocol.setXCurrent(0);
//                            shuttleProtocol.setYStart(0);
//                            shuttleProtocol.setYTarget(0);
//                            shuttleProtocol.setYCurrent(0);
//                            return;
//                        }
//                    }
//                    return;
//                }
//
//                //调度去库位
//                Task task = shuttleDispatcher.generateMoveTask(device, locNo);
//                if (task == null) {
//                    return;//调度失败
//                }
//
//                shuttleProtocol.setXCurrent(xCurrent + 1);
//                if (shuttleProtocol.getXCurrent() > shuttleProtocol.getXTarget()) {
//                    //x轴跑完,切换y轴
//                    shuttleProtocol.setXCurrent(shuttleProtocol.getXStart());
//                    shuttleProtocol.setYCurrent(shuttleProtocol.getYCurrent() + 1);
//
//                    if(shuttleProtocol.getYCurrent() > shuttleProtocol.getYTarget()) {
//                        //y轴也跑完了,结束跑库
//                        shuttleProtocol.setMoveLoc(false);
//                        shuttleProtocol.setMoveType(0);
//                        shuttleProtocol.setXStart(0);
//                        shuttleProtocol.setXTarget(0);
//                        shuttleProtocol.setXCurrent(0);
//                        shuttleProtocol.setYStart(0);
//                        shuttleProtocol.setYTarget(0);
//                        shuttleProtocol.setYCurrent(0);
//                        return;
//                    }
//                }
//
//            }else {//跑y轴方向,跑完y轴再切换x轴
//                Integer yCurrent = shuttleProtocol.getYCurrent();
//
//                //获取待跑库位号
//                String locNo = Utils.getLocNo(shuttleProtocol.getXCurrent(), yCurrent, lev);
//                Loc target = locService.getOne(new LambdaQueryWrapper<Loc>()
//                        .eq(Loc::getLocNo, locNo)
//                        .eq(Loc::getLocSts, LocStsType.O.val())
//                        .eq(Loc::getHostId, device.getHostId()));
//                if (target == null || shuttleProtocol.getCurrentLocNo().equals(locNo)) {//库位不存在或小车已在当前位置
//                    shuttleProtocol.setYCurrent(yCurrent + 1);
//                    if (shuttleProtocol.getYCurrent() > shuttleProtocol.getYTarget()) {
//                        //y轴跑完,切换x轴
//                        shuttleProtocol.setYCurrent(shuttleProtocol.getYStart());
//                        shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);
//
//                        if(shuttleProtocol.getXCurrent() > shuttleProtocol.getXTarget()) {
//                            //x轴也跑完了,结束跑库
//                            shuttleProtocol.setMoveLoc(false);
//                            shuttleProtocol.setMoveType(0);
//                            shuttleProtocol.setXStart(0);
//                            shuttleProtocol.setXTarget(0);
//                            shuttleProtocol.setXCurrent(0);
//                            shuttleProtocol.setYStart(0);
//                            shuttleProtocol.setYTarget(0);
//                            shuttleProtocol.setYCurrent(0);
//                            return;
//                        }
//                    }
//                    return;
//                }
//
//                //调度去库位
//                Task task = shuttleDispatcher.generateMoveTask(device, locNo);
//                if (task == null) {
//                    return;//调度失败
//                }
//
//                shuttleProtocol.setYCurrent(yCurrent + 1);
//                if (shuttleProtocol.getYCurrent() > shuttleProtocol.getYTarget()) {
//                    //y轴跑完,切换x轴
//                    shuttleProtocol.setYCurrent(shuttleProtocol.getYStart());
//                    shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);
//
//                    if(shuttleProtocol.getXCurrent() > shuttleProtocol.getXTarget()) {
//                        //x轴也跑完了,结束跑库
//                        shuttleProtocol.setMoveLoc(false);
//                        shuttleProtocol.setMoveType(0);
//                        shuttleProtocol.setXStart(0);
//                        shuttleProtocol.setXTarget(0);
//                        shuttleProtocol.setXCurrent(0);
//                        shuttleProtocol.setYStart(0);
//                        shuttleProtocol.setYTarget(0);
//                        shuttleProtocol.setYCurrent(0);
//                        return;
//                    }
//                }
//
//            }
//        } else if (shuttleProtocol.getMoveType() == 2) {//母轨道循环跑
//            Integer xCurrent = shuttleProtocol.getXCurrent();
//            Integer yCurrent = shuttleProtocol.getYCurrent();
//
//            String locNo = Utils.getLocNo(xCurrent, yCurrent, lev);
//            //调度去目标位置
//            if (shuttleProtocol.getCurrentLocNo().equals(locNo)) {
//                if (yCurrent.equals(shuttleProtocol.getYStart())) {
//                    shuttleProtocol.setYCurrent(shuttleProtocol.getYTarget());//小车和目标位置一致,切换库位
//                } else {
//                    shuttleProtocol.setYCurrent(shuttleProtocol.getYStart());//小车和目标位置一致,切换库位
//                }
//            } else {
//                Task result = shuttleDispatcher.generateMoveTask(device, locNo);
//                if (result != null) {//调度成功
//                    if (yCurrent.equals(shuttleProtocol.getYStart())) {
//                        shuttleProtocol.setYCurrent(shuttleProtocol.getYTarget());//切换库位
//                    } else {
//                        shuttleProtocol.setYCurrent(shuttleProtocol.getYStart());//切换库位
//                    }
//                }
//            }
//        } else if (shuttleProtocol.getMoveType() == 3) {//子轨道循环跑
//            Integer xCurrent = shuttleProtocol.getXCurrent();
//            Integer yCurrent = shuttleProtocol.getYCurrent();
//
//            String locNo = Utils.getLocNo(xCurrent, yCurrent, lev);
//            //调度去目标位置
//            if (shuttleProtocol.getCurrentLocNo().equals(locNo)) {
//                if (xCurrent.equals(shuttleProtocol.getXStart())) {
//                    shuttleProtocol.setXCurrent(shuttleProtocol.getXTarget());//小车和目标位置一致,切换库位
//                } else {
//                    shuttleProtocol.setXCurrent(shuttleProtocol.getXStart());//小车和目标位置一致,切换库位
//                }
//            } else {
//                Task result = shuttleDispatcher.generateMoveTask(device, locNo);
//                if (result != null) {//调度成功
//                    if (xCurrent.equals(shuttleProtocol.getXStart())) {
//                        shuttleProtocol.setXCurrent(shuttleProtocol.getXTarget());//切换库位
//                    } else {
//                        shuttleProtocol.setXCurrent(shuttleProtocol.getXStart());//切换库位
//                    }
//                }
//            }
//        } else if (shuttleProtocol.getMoveType() == 4) {//取放货
//            Integer xCurrent = shuttleProtocol.getXCurrent();
//            if (xCurrent > shuttleProtocol.getXTarget()) {//当X值大于X目标值
//                shuttleProtocol.setXCurrent(shuttleProtocol.getXStart());
//                shuttleProtocol.setYCurrent(shuttleProtocol.getYStart());
//                return;
//            }
//
//            //判断x轴货位是否放满
//            boolean flag = true;
//            for (Loc loc : locService.list(new LambdaQueryWrapper<Loc>()
//                    .eq(Loc::getHostId, device.getHostId())
//                    .eq(Loc::getRow, xCurrent)
//                    .ge(Loc::getBay, shuttleProtocol.getYStart())
//                    .le(Loc::getBay, shuttleProtocol.getYTarget()))) {
//                if (loc.getLocSts() != LocStsType.F.val()) {
//                    flag = false;//未满
//                    break;
//                }
//            }
//            if (flag) {
//                shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);
//                return;
//            }
//
//            //搜索有货库位
//            List<Loc> list = locService.list(new LambdaQueryWrapper<Loc>()
//                    .eq(Loc::getLocSts, LocStsType.F.val())
//                    .eq(Loc::getHostId, device.getHostId())
//                    .notIn(Loc::getRow, xCurrent)
//                    .eq(Loc::getStatus, 1));
//            if (list.isEmpty()) {
//                return;
//            }
//
//            Loc start = list.get(0);
//
//            List<Loc> locList = locService.list(new LambdaQueryWrapper<Loc>()
//                    .eq(Loc::getHostId, device.getHostId())
//                    .eq(Loc::getStatus, 1)
//                    .eq(Loc::getLocSts, LocStsType.O.val())
//                    .eq(Loc::getRow, xCurrent)
//                    .orderByDesc(Loc::getBay)
//                    .orderByAsc(Loc::getRow));
//            if (locList.isEmpty()) {
//                return;
//            }
//
//            Loc target = locList.get(0);
//            if (target == null) {
//                return;
//            }
//
//            //调度去目标位置
//            if (!shuttleProtocol.getCurrentLocNo().equals(target.getLocNo())) {
//                Task task = shuttleDispatcher.generateManuaTakeMoveTask(device, start.getLocNo(), target.getLocNo());
////                if(task != null) {//调度成功
////                    shuttleProtocol.setXCurrent(shuttleProtocol.getXCurrent() + 1);
////                }
//            }
//        }
//    }
    private synchronized CommandResponse write(ShuttleCommand command, Integer shuttleNo) {
        CommandResponse response = new CommandResponse(false);
        if (null == command) {
            News.error("四向穿梭车写入命令为空");
            response.setMessage("四向穿梭车写入命令为空");
            return response;
        }
        ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
        if (command.getMode() == ShuttleCommandModeType.MOVE.id
                || command.getMode() == ShuttleCommandModeType.IN_LIFT.id
                || command.getMode() == ShuttleCommandModeType.OUT_LIFT.id) {//移动
            response = shuttleThread.move(command);
        } else if (command.getMode() == ShuttleCommandModeType.PALLET_LIFT.id
                || command.getMode() == ShuttleCommandModeType.PALLET_DOWN.id) {//顶升
            response = shuttleThread.lift(command);
        } else if (command.getMode() == ShuttleCommandModeType.CHARGE_OPEN.id
                || command.getMode() == ShuttleCommandModeType.CHARGE_CLOSE.id) {//充电
            response = shuttleThread.charge(command);
        } else if (command.getMode() == ShuttleCommandModeType.RESET.id) {//复位
            response = shuttleThread.reset(command);
        } else if (command.getMode() == ShuttleCommandModeType.UPDATE_LOCATION.id) {//更新坐标
            response = shuttleThread.updateLocation(command);
        }
        News.info("四向穿梭车命令下发,穿梭车号={},任务数据={}", shuttleNo, JSON.toJSON(command));
        return response;
    }
}
src/main/java/com/zy/core/cache/OutputQueue.java
@@ -21,5 +21,7 @@
    public static ArrayBlockingQueue<String> SHUTTLE = new ArrayBlockingQueue<>(32);
    //提升机输出日志
    public static ArrayBlockingQueue<String> LIFT = new ArrayBlockingQueue<>(32);
    //货叉提升机输出日志
    public static ArrayBlockingQueue<String> FORKLIFT = new ArrayBlockingQueue<>(32);
}
src/main/java/com/zy/core/dispatcher/ShuttleDispatchUtils.java
File was renamed from src/main/java/com/zy/common/utils/ShuttleDispatchUtils.java
@@ -1,32 +1,25 @@
package com.zy.common.utils;
package com.zy.core.dispatcher;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.SpringUtils;
import com.core.exception.CoolException;
import com.zy.asrs.entity.BasShuttle;
import com.zy.asrs.entity.WrkCharge;
import com.zy.asrs.entity.WrkMast;
import com.zy.asrs.mapper.WrkChargeMapper;
import com.zy.asrs.mapper.WrkMastMapper;
import com.zy.asrs.service.BasShuttleService;
import com.zy.asrs.service.WrkMastService;
import com.zy.asrs.utils.Utils;
import com.zy.common.model.NavigateNode;
import com.zy.common.model.enums.NavigationMapType;
import com.zy.common.service.CommonService;
import com.zy.common.utils.ForkLiftUtils;
import com.zy.common.utils.NavigateUtils;
import com.zy.core.News;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.ShuttleChargeType;
import com.zy.core.enums.SlaveType;
import com.zy.core.model.LiftSlave;
import com.zy.core.enums.WrkStsType;
import com.zy.core.model.ForkLiftSlave;
import com.zy.core.model.ShuttleSlave;
import com.zy.core.model.protocol.LiftProtocol;
import com.zy.core.model.protocol.LiftStaProtocol;
import com.zy.core.model.protocol.NyShuttleProtocol;
import com.zy.core.model.protocol.*;
import com.zy.core.properties.SlaveProperties;
import com.zy.core.thread.LiftThread;
import com.zy.core.thread.NyShuttleThread;
import com.zy.core.thread.ForkLiftThread;
import com.zy.core.thread.ShuttleThread;
import com.zy.system.entity.Config;
import com.zy.system.service.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -46,20 +39,16 @@
    @Autowired
    private WrkMastService wrkMastService;
    @Autowired
    private WrkMastMapper wrkMastMapper;
    @Autowired
    private WrkChargeMapper wrkChargeMapper;
    @Autowired
    private CommonService commonService;
    @Autowired
    private NavigateUtils navigateUtils;
    @Autowired
    private ConfigService configService;
    /**
     * 调度车辆-调度指定穿梭车
     */
    public boolean dispatchShuttle(Integer wrkNo, String locNo, Integer shuttleNo) {
        if (!checkCharge(shuttleNo, locNo)) {
            News.info("{}号小车,存在充电任务禁止小车移动任务调度", shuttleNo);
            return false;//存在充电任务暂停调度
        }
        return shuttleMoveGenerate(wrkNo, locNo, shuttleNo);
    }
@@ -68,7 +57,7 @@
     */
    public boolean dispatchShuttle(Integer wrkNo, String locNo) {
        //检测目标库位组是否存在小车,如存在小车则直接指定该车
        WrkMast wrkMast = wrkMastMapper.selectByWorkNo(wrkNo);
        WrkMast wrkMast = wrkMastService.selectByWorkNo(wrkNo);
        if (wrkMast != null) {
            String targetLocNo = wrkMast.getIoType() < 100 ? wrkMast.getLocNo() : wrkMast.getSourceLocNo();
            List<String> groupLoc = Utils.getGroupLoc(targetLocNo);
@@ -79,13 +68,13 @@
            }
        }
        ArrayList<NyShuttleThread> sameLev = new ArrayList<>();//相同楼层的穿梭车
        ArrayList<NyShuttleThread> diffLev = new ArrayList<>();//不同楼层的穿梭车
        ArrayList<ShuttleThread> sameLev = new ArrayList<>();//相同楼层的穿梭车
        ArrayList<ShuttleThread> diffLev = new ArrayList<>();//不同楼层的穿梭车
        for (ShuttleSlave shuttle : slaveProperties.getShuttle()) {
            //获取四向穿梭车线程
            NyShuttleThread shuttleThread = (NyShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttle.getId());
            NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
            ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttle.getId());
            ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
            if (shuttleProtocol == null || shuttleProtocol.getShuttleNo() == null) {
                continue;
            }
@@ -94,30 +83,20 @@
                continue;//存在充电任务,过滤小车
            }
            if (!shuttleProtocol.isIdle()) {
            if (!shuttleThread.isIdle()) {
                continue;//小车忙碌中
            }
            if (shuttleProtocol.getSuspendState() == 1) {
                //小车处于管制中
                continue;
            }
            if (shuttleProtocol.getWorkingMode() == 0) {
                //小车处于手动模式
                continue;
            }
            int currentLev = shuttleProtocol.getPoint().getZ();//小车当前层高
            int currentLev = Utils.getLev(shuttleProtocol.getCurrentLocNo());//小车当前层高
            String currentLocNo = shuttleProtocol.getCurrentLocNo();//小车当前库位号
            if (currentLocNo.equals(locNo)) {
                //车辆当前位置已经是目标库位,调度该车
                //给工作档绑定小车号
                WrkMast wrkMast1 = wrkMastMapper.selectByWorkNo(wrkNo);
                WrkMast wrkMast1 = wrkMastService.selectByWorkNo(wrkNo);
                if (wrkMast1 != null) {
                    wrkMast1.setShuttleNo(shuttleProtocol.getShuttleNo().intValue());
                    wrkMastMapper.updateById(wrkMast1);
                    wrkMast1.setShuttleNo(shuttleProtocol.getShuttleNo());
                    wrkMastService.updateById(wrkMast1);
                    return true;
                }
                break;
@@ -135,24 +114,28 @@
        //优先调度同楼层小车,寻找离任务最近的穿梭车
        if (!sameLev.isEmpty()) {
            Map<Integer, NyShuttleThread> sameShuttles = new TreeMap<>();//自然排序小车Map
            for (NyShuttleThread shuttleThread : sameLev) {
            Map<Integer, ShuttleThread> sameShuttles = new TreeMap<>();//自然排序小车Map
            for (ShuttleThread shuttleThread : sameLev) {
                ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
                Integer shuttleNo = shuttleProtocol.getShuttleNo();
                //当前穿梭车库位号
                String currentLocNo = shuttleThread.getShuttleProtocol().getCurrentLocNo();
                String currentLocNo = shuttleProtocol.getCurrentLocNo();
                //当前穿梭车线程到目标地点距离
                List<NavigateNode> currentShuttlePath = NavigateUtils.calc(currentLocNo, locNo, NavigationMapType.NORMAL.id, Utils.getShuttlePoints(shuttleThread.getSlave().getId(), Utils.getLev(currentLocNo)), null);//搜索空闲穿梭车,使用正常通道地图
                List<NavigateNode> currentShuttlePath = navigateUtils.calc(currentLocNo, locNo, NavigationMapType.NORMAL.id, Utils.getShuttlePoints(shuttleNo, Utils.getLev(currentLocNo)), null);//搜索空闲穿梭车,使用正常通道地图
                if (currentShuttlePath == null) {
                    continue;
                }
                Integer currentAllDistance = NavigateUtils.getOriginPathAllDistance(currentShuttlePath);//计算当前路径行走总距离
                Integer currentAllDistance = navigateUtils.getOriginPathAllDistance(currentShuttlePath);//计算当前路径行走总距离
                sameShuttles.put(currentAllDistance, shuttleThread);
            }
            //尝试调度同楼层小车
            for (Map.Entry<Integer, NyShuttleThread> entry : sameShuttles.entrySet()) {
                NyShuttleThread shuttleThread = entry.getValue();
            for (Map.Entry<Integer, ShuttleThread> entry : sameShuttles.entrySet()) {
                ShuttleThread shuttleThread = entry.getValue();
                ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
                Integer shuttleNo = shuttleProtocol.getShuttleNo();
                //尝试调度小车
                boolean result = shuttleMoveGenerate(wrkNo, locNo, shuttleThread.getSlave().getId());
                boolean result = shuttleMoveGenerate(wrkNo, locNo, shuttleNo);
                if (result) {
                    return true;//调度成功
                }
@@ -162,9 +145,9 @@
        //执行到此处,同楼层无调度成功小车。需要进行跨楼层调度小车
        //寻找离任务楼层最近的穿梭车(不考虑跨楼层小车移动距离)
        if (!diffLev.isEmpty()) {
            Map<Integer, NyShuttleThread> diffShuttles = new TreeMap<>();//自然排序小车Map
            Map<Integer, ShuttleThread> diffShuttles = new TreeMap<>();//自然排序小车Map
            //获取任务
            WrkMast wrkMast1 = wrkMastMapper.selectByWorkNo(wrkNo);
            WrkMast wrkMast1 = wrkMastService.selectByWorkNo(wrkNo);
            if (wrkMast1 != null) {
                String targetLoc = wrkMast1.getIoType() < 100 ? wrkMast1.getLocNo() : wrkMast1.getSourceLocNo();
                int lev = Utils.getLev(targetLoc);//目标楼层
@@ -176,9 +159,10 @@
                    return false;
                }
                for (NyShuttleThread shuttleThread : diffLev) {
                for (ShuttleThread shuttleThread : diffLev) {
                    ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
                    //当前穿梭车库位号
                    String currentLocNo = shuttleThread.getShuttleProtocol().getCurrentLocNo();
                    String currentLocNo = shuttleProtocol.getCurrentLocNo();
                    int currentLev = Utils.getLev(currentLocNo);
                    List<WrkMast> wrkMasts1 = wrkMastService.selectNoShuttleWrkByLev(currentLev);//判断当前穿梭车楼层是否有待分配车辆的任务,如果有则不分配这辆车
                    int shuttleCount = this.getShuttleCountByLev(currentLev);//获取穿梭车楼层车辆数量
@@ -193,10 +177,12 @@
                }
                //尝试调度跨楼层小车
                for (Map.Entry<Integer, NyShuttleThread> entry : diffShuttles.entrySet()) {
                    NyShuttleThread shuttleThread = entry.getValue();
                for (Map.Entry<Integer, ShuttleThread> entry : diffShuttles.entrySet()) {
                    ShuttleThread shuttleThread = entry.getValue();
                    ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
                    Integer shuttleNo = shuttleProtocol.getShuttleNo();
                    //尝试调度小车
                    boolean result = shuttleMoveGenerate(wrkNo, locNo, shuttleThread.getSlave().getId());
                    boolean result = shuttleMoveGenerate(wrkNo, locNo, shuttleNo);
                    if (result) {
                        return true;//调度成功
                    }
@@ -215,32 +201,32 @@
    public boolean shuttleMoveGenerate(Integer wrkNo, String locNo, Integer shuttleNo) {
        Date now = new Date();
        //获取四向穿梭车线程
        NyShuttleThread shuttleThread = (NyShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
        ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
        if (shuttleThread == null) {
            News.info("{}号小车,线程不存在", shuttleNo);
            return false;
        }
        NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
        ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
        if (shuttleProtocol == null) {
            News.info("{}号小车,线程不存在", shuttleNo);
            return false;
        }
        //小车处于空闲状态
        if (!shuttleProtocol.isIdleNoCharge()) {
        if (!shuttleThread.isIdle()) {
            News.info("{}号小车,忙碌中", shuttleNo);
            return false;
        }
        //判断穿梭车是否存在未完成的小车移库任务
        WrkMast hasMoveWorking = wrkMastMapper.selectShuttleHasMoveWorking(shuttleNo);
        WrkMast hasMoveWorking = wrkMastService.selectShuttleHasMoveWorking(shuttleNo);
        if (hasMoveWorking != null) {//小车存在移库任务,等待执行完成后再生成新的任务
            News.info("{}号小车,存在移动任务,等待执行完成后再生成新的任务", shuttleNo);
            return false;
        }
        //判断是否有其他任务正在使用穿梭车
        WrkMast wrkMast2 = wrkMastMapper.selectShuttleWorking(shuttleNo);
        WrkMast wrkMast2 = wrkMastService.selectShuttleWorking(shuttleNo);
        if (wrkMast2 != null) {//小车存在其他工作档任务,等待执行完成后再生成新的任务
            News.info("{}号小车,存在其他工作档任务,等待执行完成再生成新的任务", shuttleNo);
            return false;
@@ -248,10 +234,10 @@
        Integer sourceStaNo = null;//小车换层源站点
        Integer staNo = null;//小车换层目标站点
        if (Utils.getLev(locNo) != shuttleProtocol.getPoint().getZ()) {
        if (Utils.getLev(locNo) != Utils.getLev(shuttleProtocol.getCurrentLocNo())) {
            //目标库位和小车库位处于不同一楼层,需要通过提升机调度
            //获取穿梭车最近且空闲的提升机输送站点
            LiftStaProtocol liftSta = this.getRecentLiftSta(shuttleNo, Utils.getLev(locNo));
            ForkLiftStaProtocol liftSta = this.getRecentLiftSta(shuttleNo, Utils.getLev(locNo));
            if (liftSta == null) {
                News.info("{}号小车,{}目标库位,没有可用空闲输送站点", shuttleNo, locNo);
                return false;//没有可用且空闲的输送站点
@@ -267,30 +253,27 @@
        WrkMast wrkMast = new WrkMast();
        wrkMast.setWrkNo(workNo);
        wrkMast.setIoTime(now);
        wrkMast.setWrkSts(101L); // 工作状态:101.移动到近点等待迁出
        wrkMast.setIoType(200); // 入出库状态: 200.小车移库
        wrkMast.setWrkSts(WrkStsType.NEW_MOVE.sts); // 工作状态:301.生成迁移任务
        wrkMast.setIoType(200); // 入出库状态: 200.小车迁移
        wrkMast.setIoPri(20D);
        wrkMast.setShuttleNo(shuttleNo);//穿梭车号
        wrkMast.setSourceLocNo(shuttleProtocol.getCurrentLocNo()); // 源库位 => 小车当前库位号
        wrkMast.setLocNo(locNo); // 目标库位
        wrkMast.setSourceStaNo(sourceStaNo);//源站
        wrkMast.setStaNo(staNo);//目标站
        wrkMast.setPicking("N"); // 拣料
        wrkMast.setExitMk("N"); // 退出
        wrkMast.setLinkMis("N");
        wrkMast.setAppeTime(now);
        wrkMast.setModiTime(now);
        int res = wrkMastMapper.insert(wrkMast);
        if (res == 0) {
        boolean res = wrkMastService.insert(wrkMast);
        if (!res) {
            News.error("小车迁移 --- 保存工作档失败! 穿梭车号:" + shuttleNo);
            throw new CoolException("保存工作档失败");
        }
        //给工作档绑定小车号
        WrkMast wrkMast1 = wrkMastMapper.selectByWorkNo(wrkNo);
        WrkMast wrkMast1 = wrkMastService.selectByWorkNo(wrkNo);
        if (wrkMast1 != null) {
            wrkMast1.setShuttleNo(shuttleNo);
            wrkMastMapper.updateById(wrkMast1);
            wrkMastService.updateById(wrkMast1);
        }
        return true;
@@ -301,8 +284,6 @@
     * true: 小于最大数量  false: 大于或等于最大数量
     */
    public boolean checkDispatchMaxNum(Integer lev) {
        BasShuttleService basShuttleService = SpringUtils.getBean(BasShuttleService.class);
        ConfigService configService = SpringUtils.getBean(ConfigService.class);
        EntityWrapper<Config> wrapper = new EntityWrapper<>();
        wrapper.eq("code", "dispatchShuttleMaxNum");
        Config config = configService.selectOne(wrapper);
@@ -313,34 +294,28 @@
        int levCount = 0;//目标楼层车辆数量
        for (ShuttleSlave shuttle : slaveProperties.getShuttle()) {
            //获取四向穿梭车线程
            NyShuttleThread shuttleThread = (NyShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttle.getId());
            NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
            ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttle.getId());
            ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
            if (shuttleProtocol == null || shuttleProtocol.getShuttleNo() == null) {
                continue;
            }
            NyShuttleProtocol.NyShuttlePointClass point = null;
            if (shuttleProtocol.getPoint() == null) {
            String currentLocNo = shuttleProtocol.getCurrentLocNo();
            if (currentLocNo == null) {
                continue;
            }else {
                point = shuttleProtocol.getPoint();
            }
            int currentLev = Utils.getLev(currentLocNo);
            if (point.getZ().equals(lev)) {
                if (shuttleProtocol.getChargState() == 1) {
                    continue;//充电中
            if (lev == currentLev) {
                if (shuttleThread.isCharging()) {
                    continue;
                }
                if (shuttleProtocol.getSuspendState() == 1) {
                    continue;//管制中
                }
                levCount++;//目标楼层有车,数量增加
            }
        }
        //搜索是否存在前往目标楼层的小车移动工作档
        for (WrkMast wrkMast : wrkMastMapper.selectShuttleMoveWrk()) {
        for (WrkMast wrkMast : wrkMastService.selectShuttleMoveWrk()) {
            if (wrkMast.getSourceLocNo() == null || wrkMast.getLocNo() == null) {
                continue;
            }
@@ -364,40 +339,40 @@
    /**
     * 获取穿梭车最近且空闲的提升机输送站点
     */
    public LiftStaProtocol getRecentLiftSta(Integer shuttleNo, Integer targetLev) {
    public ForkLiftStaProtocol getRecentLiftSta(Integer shuttleNo, Integer targetLev) {
        //获取四向穿梭车线程
        NyShuttleThread shuttleThread = (NyShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
        ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo);
        if (shuttleThread == null) {
            return null;
        }
        NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
        ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
        if (shuttleProtocol == null) {
            return null;
        }
        //获取小车同一楼层的站点
        ArrayList<LiftStaProtocol> list = new ArrayList<>();
        ArrayList<ForkLiftStaProtocol> list = new ArrayList<>();
        int lev = Utils.getLev(shuttleProtocol.getCurrentLocNo());//小车楼层
        for (LiftSlave slave : slaveProperties.getLift()) {
            LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, slave.getId());
            if (liftThread == null) {
        for (ForkLiftSlave slave : slaveProperties.getForkLift()) {
            ForkLiftThread forkLiftThread = (ForkLiftThread) SlaveConnection.get(SlaveType.ForkLift, slave.getId());
            if (forkLiftThread == null) {
                continue;
            }
            LiftProtocol liftProtocol = liftThread.getLiftProtocol();
            if (liftProtocol == null) {
            ForkLiftProtocol forkLiftProtocol = forkLiftThread.getStatus();
            if (forkLiftProtocol == null) {
                continue;
            }
            if (!liftProtocol.isIdle()) {
            if (!forkLiftThread.isIdle()) {
                continue;
            }
            LiftStaProtocol liftStaProtocol = NyLiftUtils.getLiftStaByLev(slave.getId(), lev);
            if (liftStaProtocol == null) {
            ForkLiftStaProtocol forkLiftStaProtocol = ForkLiftUtils.getLiftStaByLev(slave.getId(), lev);
            if (forkLiftStaProtocol == null) {
                continue;
            }
            //判断目标楼层站点是否无托盘
            LiftStaProtocol targetLiftStaProtocol = NyLiftUtils.getLiftStaByLev(slave.getId(), targetLev);
            ForkLiftStaProtocol targetLiftStaProtocol = ForkLiftUtils.getLiftStaByLev(slave.getId(), targetLev);
            if (targetLiftStaProtocol == null) {
                continue;
            }
@@ -406,7 +381,7 @@
                continue;//有托盘跳过
            }
            list.add(liftStaProtocol);
            list.add(forkLiftStaProtocol);
        }
        if (list.isEmpty()) {
@@ -415,21 +390,21 @@
        String currentLocNo = shuttleProtocol.getCurrentLocNo();//小车位置
        Integer recentAllDistance = 9999999;
        LiftStaProtocol recentSta = null;//最近站点
        ForkLiftStaProtocol recentSta = null;//最近站点
        //搜索距离小车最近的站点
        for (LiftStaProtocol liftStaProtocol : list) {
            Integer staNo = liftStaProtocol.getStaNo();//站点号
            String locNo = liftStaProtocol.getLocNo();//站点库位号
        for (ForkLiftStaProtocol forkLiftStaProtocol : list) {
            Integer staNo = forkLiftStaProtocol.getStaNo();//站点号
            String locNo = forkLiftStaProtocol.getLocNo();//站点库位号
            //当前穿梭车线程到目标地点距离
            List<NavigateNode> currentShuttlePath = NavigateUtils.calc(currentLocNo, locNo, NavigationMapType.NORMAL.id, Utils.getShuttlePoints(shuttleNo, Utils.getLev(currentLocNo)), null);//使用正常通道地图
            List<NavigateNode> currentShuttlePath = navigateUtils.calc(currentLocNo, locNo, NavigationMapType.NORMAL.id, Utils.getShuttlePoints(shuttleNo, Utils.getLev(currentLocNo)), null);//使用正常通道地图
            if (currentShuttlePath == null) {
                continue;
            }
            Integer currentAllDistance = NavigateUtils.getOriginPathAllDistance(currentShuttlePath);//计算当前路径行走总距离
            Integer currentAllDistance = navigateUtils.getOriginPathAllDistance(currentShuttlePath);//计算当前路径行走总距离
            if (currentAllDistance < recentAllDistance) {
                //如果当前楼层的车路径更小,则更新最近站点
                recentSta = liftStaProtocol;
                recentSta = forkLiftStaProtocol;
                recentAllDistance = currentAllDistance;
            }
        }
@@ -442,42 +417,11 @@
     */
    public boolean checkChargeWrk(int shuttleNo) {
        //判断是否有充电任务正在使用穿梭车
        WrkCharge wrkCharge = wrkChargeMapper.selectWorking(shuttleNo);
        if (wrkCharge != null) {
        WrkMast wrkMast = wrkMastService.selectChargeWorking(shuttleNo);
        if (wrkMast != null) {
            return true;//有充电任务
        }
        return false;//无充电任务
    }
    /**
     * 检测穿梭车是否有充电任务,目标点是否为充电桩位置
     * @param shuttleNo 小车号
     * @param locNo 目标位置
     */
    public boolean checkCharge(int shuttleNo, String locNo) {
        //判断是否有充电任务正在使用穿梭车
        WrkCharge wrkCharge = wrkChargeMapper.selectWorking(shuttleNo);
        if (wrkCharge != null) {//小车存在充电任务,等待执行完成后再生成新的任务
            //判断目标点是否为充电桩,如果是去充电则放行
            boolean toCharge = false;//去充电目标
            for (ShuttleChargeType chargeType : ShuttleChargeType.values()) {
                if (chargeType.locNo.equals(locNo)) {
                    toCharge = true;//去充电桩
                    break;
                }
            }
            if (wrkCharge.getWrkSts() == 53) {
                toCharge = true;//充电结束,允许生成移库任务
            }
            if (!toCharge) {
                //不是去充电桩且存在充电任务,禁止生成新的移动任务
                return false;
            }
        }
        return true;//无充电任务放行 || 去充电桩中放行
    }
    /**
@@ -487,12 +431,12 @@
        int count = 0;
        for (ShuttleSlave slave : slaveProperties.getShuttle()) {
            //获取四向穿梭车线程
            NyShuttleThread shuttleThread = (NyShuttleThread) SlaveConnection.get(SlaveType.Shuttle, slave.getId());
            ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, slave.getId());
            if (shuttleThread == null) {
                continue;
            }
            NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol();
            ShuttleProtocol shuttleProtocol = shuttleThread.getStatus();
            if (shuttleProtocol == null || shuttleProtocol.getShuttleNo() == null) {
                continue;
            }
@@ -501,16 +445,11 @@
                continue;//存在充电任务,过滤小车
            }
            if (shuttleProtocol.getWorkingMode() == 0) {
                continue;//手动状态
            }
            if (shuttleProtocol.getSuspendState() == 1) {
                //小车处于管制中
            if (!shuttleThread.isIdle()) {
                continue;
            }
            if (shuttleProtocol.getPoint().getZ() == lev) {
            if (Utils.getLev(shuttleProtocol.getCurrentLocNo()) == lev) {
                //同一楼层可用小车
                count++;
                continue;
src/main/java/com/zy/core/enums/CrnFingerPosType.java
File was deleted
src/main/java/com/zy/core/enums/CrnForkPosType.java
File was deleted
src/main/java/com/zy/core/enums/CrnLiftPosType.java
File was deleted
src/main/java/com/zy/core/enums/CrnModeType.java
File was deleted
src/main/java/com/zy/core/enums/CrnStatusType.java
File was deleted
src/main/java/com/zy/core/enums/CrnTaskModeType.java
File was deleted
src/main/java/com/zy/core/enums/ForkLiftConfirmType.java
New file
@@ -0,0 +1,40 @@
package com.zy.core.enums;
//货叉提升机任务确认
public enum ForkLiftConfirmType {
    NO(0, "未确认"),
    CONFIRM(1, "已确认"),
    ;
    public Integer id;
    public String desc;
    ForkLiftConfirmType(Integer id, String desc) {
        this.id = id;
        this.desc = desc;
    }
    public static ForkLiftConfirmType get(Integer id) {
        if (null == id) {
            return null;
        }
        for (ForkLiftConfirmType type : ForkLiftConfirmType.values()) {
            if (type.id.equals(id)) {
                return type;
            }
        }
        return null;
    }
    public static ForkLiftConfirmType get(ForkLiftConfirmType type) {
        if (null == type) {
            return null;
        }
        for (ForkLiftConfirmType type2 : ForkLiftConfirmType.values()) {
            if (type2 == type) {
                return type2;
            }
        }
        return null;
    }
}
src/main/java/com/zy/core/enums/ForkLiftIoModeType.java
New file
@@ -0,0 +1,41 @@
package com.zy.core.enums;
//货叉提升机出入库模式
public enum ForkLiftIoModeType {
    NONE(0, "未知"),
    IN(1, "入库"),
    OUT(2, "出库"),
    ;
    public Integer id;
    public String desc;
    ForkLiftIoModeType(Integer id, String desc) {
        this.id = id;
        this.desc = desc;
    }
    public static ForkLiftIoModeType get(Integer id) {
        if (null == id) {
            return null;
        }
        for (ForkLiftIoModeType type : ForkLiftIoModeType.values()) {
            if (type.id.equals(id)) {
                return type;
            }
        }
        return null;
    }
    public static ForkLiftIoModeType get(ForkLiftIoModeType type) {
        if (null == type) {
            return null;
        }
        for (ForkLiftIoModeType type2 : ForkLiftIoModeType.values()) {
            if (type2 == type) {
                return type2;
            }
        }
        return null;
    }
}
src/main/java/com/zy/core/enums/ForkLiftProtocolStatusType.java
New file
@@ -0,0 +1,43 @@
package com.zy.core.enums;
public enum ForkLiftProtocolStatusType {
    NONE(-1, "离线"),
    IDLE(0, "空闲"),
    PICK_UP(1, "取货中"),
    PUT_DOWN(2, "放货中"),
    WAITING(98, "等待确认"),
    ERROR(99, "故障"),
    ;
    public Integer id;
    public String desc;
    ForkLiftProtocolStatusType(Integer id, String desc) {
        this.id = id;
        this.desc = desc;
    }
    public static ForkLiftProtocolStatusType get(Integer id) {
        if (null == id) {
            return null;
        }
        for (ForkLiftProtocolStatusType type : ForkLiftProtocolStatusType.values()) {
            if (type.id.equals(id)) {
                return type;
            }
        }
        return null;
    }
    public static ForkLiftProtocolStatusType get(ForkLiftProtocolStatusType type) {
        if (null == type) {
            return null;
        }
        for (ForkLiftProtocolStatusType type2 : ForkLiftProtocolStatusType.values()) {
            if (type2 == type) {
                return type2;
            }
        }
        return null;
    }
}
src/main/java/com/zy/core/enums/ForkLiftTaskModeType.java
New file
@@ -0,0 +1,44 @@
package com.zy.core.enums;
//货叉提升机任务模式
public enum ForkLiftTaskModeType {
    NONE(0, "未知"),
    PICK_UP(1, "取货"),
    PUT_DOWN(2, "放货"),
    PICK_PUT(3, "取放货"),
    SHUTTLE_SWITCH(4, "小车换层"),
    ;
    public Integer id;
    public String desc;
    ForkLiftTaskModeType(Integer id, String desc) {
        this.id = id;
        this.desc = desc;
    }
    public static ForkLiftTaskModeType get(Integer id) {
        if (null == id) {
            return null;
        }
        for (ForkLiftTaskModeType type : ForkLiftTaskModeType.values()) {
            if (type.id.equals(id)) {
                return type;
            }
        }
        return null;
    }
    public static ForkLiftTaskModeType get(ForkLiftTaskModeType type) {
        if (null == type) {
            return null;
        }
        for (ForkLiftTaskModeType type2 : ForkLiftTaskModeType.values()) {
            if (type2 == type) {
                return type2;
            }
        }
        return null;
    }
}
src/main/java/com/zy/core/enums/LiftLevType.java
File was deleted
src/main/java/com/zy/core/enums/LiftNotReadyType.java
File was deleted
src/main/java/com/zy/core/enums/LiftProtocolStatusType.java
File was deleted
src/main/java/com/zy/core/enums/LocStsType.java
New file
@@ -0,0 +1,27 @@
package com.zy.core.enums;
public enum LocStsType {
    D,//空板
    F,//在库
    O,//空库
    X,//禁用
    E,//不可放货通道
    W,//母轨道
    C,//充电桩
    Z,//站点
    ;
    LocStsType() {
    }
    public static LocStsType get(String el) {
        for (LocStsType value : LocStsType.values()) {
            if (el.equals(value.toString())) {
                return value;
            }
        }
        return null;
    }
}
src/main/java/com/zy/core/enums/MapNodeType.java
New file
@@ -0,0 +1,49 @@
package com.zy.core.enums;
public enum MapNodeType {
    DISABLE(-1, "禁用"),
    NORMAL_PATH(0, "货位"),
    START_POINT(1, "起点"),
    TARGET_POINT(2, "终点"),
    MAIN_PATH(3, "母轨"),
    CONVEYOR(4, "输送站点"),
    CHARGE(5, "充电桩"),
    CONVEYOR_CAR_GO(6, "小车可走输送站点"),
    CAR(66, "小车"),
    LIFT(67, "提升机"),
    LOCK(-999, "锁定节点"),
    ;
    public Integer id;
    public String desc;
    MapNodeType(Integer id, String desc) {
        this.id = id;
        this.desc = desc;
    }
    public static MapNodeType get(Short id) {
        if (null == id) {
            return null;
        }
        for (MapNodeType type : MapNodeType.values()) {
            if (type.id.equals(id.intValue())) {
                return type;
            }
        }
        return null;
    }
    public static MapNodeType get(MapNodeType type) {
        if (null == type) {
            return null;
        }
        for (MapNodeType type1 : MapNodeType.values()) {
            if (type1 == type) {
                return type1;
            }
        }
        return null;
    }
}
src/main/java/com/zy/core/enums/NyLiftTaskModelType.java
File was deleted
src/main/java/com/zy/core/enums/RedisKeyType.java
@@ -4,6 +4,7 @@
    SHUTTLE("shuttle_wrk_no_"),
    LIFT("lift_wrk_no_"),
    FORK_LIFT("fork_lift_wrk_no_"),
    MAP("realtimeBasMap_"),
    BASIC_MAP("basicMap_"),
    ;
src/main/java/com/zy/core/enums/ShuttleChargeType.java
File was deleted
src/main/java/com/zy/core/enums/ShuttleCommandModeType.java
New file
@@ -0,0 +1,53 @@
package com.zy.core.enums;
/**
 * 四向穿梭车命令类型
 */
public enum ShuttleCommandModeType {
    NONE(-1, "未知类型"),
    MOVE(1, "移动"),
    IN_LIFT(2, "进提升机"),
    OUT_LIFT(3, "出提升机"),
    CHARGE_OPEN(4, "充电开"),
    CHARGE_CLOSE(5, "充电关"),
    PALLET_LIFT(6, "托盘顶升"),
    PALLET_DOWN(7, "托盘下降"),
    RESET(8, "复位"),
    UPDATE_LOCATION(9, "更新坐标"),
    ;
    public Integer id;
    public String desc;
    ShuttleCommandModeType(Integer id, String desc) {
        this.id = id;
        this.desc = desc;
    }
    public static ShuttleCommandModeType get(Integer id) {
        if (null == id) {
            return null;
        }
        for (ShuttleCommandModeType type : ShuttleCommandModeType.values()) {
            if (type.id.equals(id)) {
                return type;
            }
        }
        return null;
    }
    public static ShuttleCommandModeType get(ShuttleCommandModeType type) {
        if (null == type) {
            return null;
        }
        for (ShuttleCommandModeType type1 : ShuttleCommandModeType.values()) {
            if (type1 == type) {
                return type1;
            }
        }
        return null;
    }
}
src/main/java/com/zy/core/enums/ShuttleErrorCodeType.java
File was deleted
src/main/java/com/zy/core/enums/ShuttlePlcInputStatusType.java
File was deleted
src/main/java/com/zy/core/enums/ShuttlePlcOutputStatusType.java
File was deleted
src/main/java/com/zy/core/enums/ShuttleTaskModeType.java
@@ -3,29 +3,17 @@
public enum ShuttleTaskModeType {
    INIT(0, "初始"),    // 初始
    PAK_IN(1, "入库"),
    PAK_OUT(2, "出库"),
    PALLET_LIFT(3, "托盘顶升"),
    PALLET_DOWN(4, "托盘下降"),
    X_NEGATIVE(5, "X-方向"),
    X_POSITIVE(6, "X+方向"),
    Y_POSITIVE(7, "Y+方向"),
    Y_NEGATIVE(8, "Y-方向"),
    RESET(9, "状态复位"),
    SEARCH_LEFT(10, "正方向(右)寻库位"),
    SEARCH_RIGHT(11, "负方向(左)寻库位"),
    SEARCH_TOP(12, "负方向(前)寻库位"),
    SEARCH_BOTTOM(13, "负方向(后)寻库位"),
    MOVE_LOC_NO(14, "移动到目标库位"),
    CHARGE(15, "充电"),
    MOVE_LIFT(16, "移动到提升机"),
    AVOID(17, "避让任务"),
    TRANSPORT(18, "搬运任务"),
    SHUTTLE_MOVE_LOC_NO(19, "小车移库任务"),
    SHUTTLE_LOC_TO_LOC(20, "库位移转"),
    SHUTTLE_CONTROL(21, "小车管制"),
    SHUTTLE_CANCEL_CONTROL(22, "小车取消管制"),
    MOVE_LOC_NO_WRK_MAST(23, "移动到目标库位(生成移动任务)"),
    PALLET_LIFT(1, "托盘顶升"),
    PALLET_DOWN(2, "托盘下降"),
    RESET(3, "状态复位"),
    MOVE_LOC_NO(4, "移动到目标库位"),
    MOVE_LOC_NO_TASK(5, "移动到目标库位(生成移动任务)"),
    CHARGE(6, "充电"),
    MOVE_LIFT(7, "移动到提升机"),
    AVOID(8, "避让任务"),
    TRANSPORT(9, "搬运任务"),
    SHUTTLE_CONTROL(10, "小车管制"),
    SHUTTLE_CANCEL_CONTROL(11, "小车取消管制"),
    ;
    public Integer id;
@@ -36,12 +24,12 @@
        this.desc = desc;
    }
    public static ShuttleTaskModeType get(Short id) {
    public static ShuttleTaskModeType get(Integer id) {
        if (null == id) {
            return null;
        }
        for (ShuttleTaskModeType type : ShuttleTaskModeType.values()) {
            if (type.id.equals(id.intValue())) {
            if (type.id.equals(id)) {
                return type;
            }
        }
src/main/java/com/zy/core/enums/ShuttleTaskNoType.java
New file
@@ -0,0 +1,48 @@
package com.zy.core.enums;
/**
 * 四向穿梭车任务号类型
 */
public enum ShuttleTaskNoType {
    IN(1, "入库"),
    OUT(2, "出库"),
    MOVE(3, "移动"),
    CHARGE(4, "充电"),
    RESET(5, "复位"),
    ;
    public Integer id;
    public String desc;
    ShuttleTaskNoType(Integer id, String desc) {
        this.id = id;
        this.desc = desc;
    }
    public static ShuttleTaskNoType get(Integer id) {
        if (null == id) {
            return null;
        }
        for (ShuttleTaskNoType type : ShuttleTaskNoType.values()) {
            if (type.id.equals(id)) {
                return type;
            }
        }
        return null;
    }
    public static ShuttleTaskNoType get(ShuttleTaskNoType type) {
        if (null == type) {
            return null;
        }
        for (ShuttleTaskNoType type1 : ShuttleTaskNoType.values()) {
            if (type1 == type) {
                return type1;
            }
        }
        return null;
    }
}
src/main/java/com/zy/core/enums/SlaveType.java
@@ -4,8 +4,6 @@
    Crn,
    Devp,
    Devp2,
    Devp3,
    Barcode,
    Led,
    Scale,
@@ -13,6 +11,7 @@
    Ste,
    Shuttle,
    Lift,
    ForkLift,
    ;
    public static SlaveType findInstance(String s){
src/main/java/com/zy/core/enums/SteABType.java
File was deleted
src/main/java/com/zy/core/enums/SteChargeType.java
File was deleted
src/main/java/com/zy/core/enums/SteHisTaskStatusType.java
File was deleted
src/main/java/com/zy/core/enums/SteLocaType.java
File was deleted
src/main/java/com/zy/core/enums/SteStatusType.java
File was deleted
src/main/java/com/zy/core/enums/SteTaskModeType.java
File was deleted
src/main/java/com/zy/core/enums/WrkStsType.java
New file
@@ -0,0 +1,66 @@
package com.zy.core.enums;
import com.core.exception.CoolException;
public enum WrkStsType {
    NEW_INBOUND(1, "生成入库任务"),
    INBOUND_DEVICE_RUN(2, "设备上走"),
    INBOUND_LIFT_RUN(3, "提升机搬运中"),
    INBOUND_LIFT_RUN_COMPLETE(4, "提升机搬运完成"),
    INBOUND_SHUTTLE_RUN(5, "小车搬运中"),
    INBOUND_SHUTTLE_RUN_COMPLETE(6, "小车搬运完成"),
    COMPLETE_INBOUND(9, "入库完成"),
    SETTLE_INBOUND(10, "入库库存更新"),
    NEW_OUTBOUND(101, "生成出库任务"),
    OUTBOUND_SHUTTLE_RUN(102, "小车搬运中"),
    OUTBOUND_SHUTTLE_RUN_COMPLETE(103, "小车搬运完成"),
    OUTBOUND_LIFT_RUN(104, "提升机搬运中"),
    OUTBOUND_LIFT_RUN_COMPLETE(105, "提升机搬运完成"),
    COMPLETE_OUTBOUND(109, "出库完成"),
    SETTLE_OUTBOUND(110, "出库库存更新"),
    NEW_CHARGE(201, "生成充电任务"),
    CHARGE_SHUTTLE_RUN(202, "小车去充电中"),
    CHARGE_SHUTTLE_WORKING(203, "执行充电任务"),
    CHARGE_SHUTTLE_COMPLETE(204, "小车充电完成"),
    COMPLETE_CHARGE(210, "充电任务完成"),
    NEW_MOVE(301, "生成迁移任务"),
    MOVE_SITE(302, "小车移动至站点"),
    MOVE_SITE_COMPLETE(303, "小车移动至站点完成"),
    MOVE_IN_LIFT(304, "小车迁入提升机中"),
    MOVE_IN_LIFT_COMPLETE(305, "小车迁入提升机完成"),
    MOVE_LIFT_RUN(306, "提升机搬运中"),
    MOVE_LIFT_RUN_COMPLETE(307, "提升机搬运完成"),
    MOVE_OUT_LIFT(308, "小车迁出提升机中"),
    MOVE_OUT_LIFT_COMPLETE(309, "小车迁出提升机完成"),
    MOVE_SHUTTLE(310, "小车移动中"),
    COMPLETE_MOVE(311, "小车移动完成"),
    NEW_MANUAL(401, "生成手动任务"),
    ANALYZE_MANUAL(402, "手动任务解析"),
    EXECUTE_MANUAL(403, "执行手动任务"),
    COMPLETE_MANUAL(410, "手动任务完成"),
    ;
    public long sts;
    public String desc;
    WrkStsType(long sts, String desc) {
        this.sts = sts;
        this.desc = desc;
    }
    public static WrkStsType query(Long sts) {
        for (WrkStsType value : WrkStsType.values()) {
            if (value.sts == sts) {
                return value;
            }
        }
        throw new CoolException("TaskStsType Error!!!");
    }
}
src/main/java/com/zy/core/model/CommandResponse.java
New file
@@ -0,0 +1,23 @@
package com.zy.core.model;
import lombok.Data;
@Data
public class CommandResponse {
    private Boolean result;
    private String message;
    public CommandResponse() {
    }
    public CommandResponse(Boolean result) {
        this.result = result;
    }
    public CommandResponse(Boolean result, String message) {
        this.result = result;
        this.message = message;
    }
}
src/main/java/com/zy/core/model/CrnSlave.java
File was deleted
src/main/java/com/zy/core/model/Devp2Slave.java
File was deleted
src/main/java/com/zy/core/model/ForkLiftSlave.java
New file
@@ -0,0 +1,37 @@
package com.zy.core.model;
import com.zy.core.Slave;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.ArrayList;
import java.util.List;
@EqualsAndHashCode(callSuper = true)
@Data
public class ForkLiftSlave extends Slave {
    //提升机站点
    private List<Sta> sta = new ArrayList<>();
    //输送站点排
    private Integer staRow;
    //输送站点列
    private Integer staBay;
    @Data
    public static class Sta {
        // 提升机站点号
        private Integer staNo;
        // 层
        private Integer lev;
        // 提升机号
        private Integer liftNo;
    }
}
src/main/java/com/zy/core/model/PythonResult.java
New file
@@ -0,0 +1,18 @@
package com.zy.core.model;
import lombok.Data;
@Data
public class PythonResult {
    private String start;
    private String target;
    private String path;
    private Double time;
    private Integer calcResult;
}
src/main/java/com/zy/core/model/PythonSimilarityResult.java
New file
@@ -0,0 +1,16 @@
package com.zy.core.model;
import lombok.Data;
@Data
public class PythonSimilarityResult {
    private String firstPath;
    private String secondPath;
    private Double similarity;
    private Integer calcResult;
}
src/main/java/com/zy/core/model/SteSlave.java
File was deleted
src/main/java/com/zy/core/model/command/CrnCommand.java
File was deleted
src/main/java/com/zy/core/model/command/ForkLiftCommand.java
New file
@@ -0,0 +1,47 @@
package com.zy.core.model.command;
import lombok.Data;
/**
 * 货叉提升机命令报文
 */
@Data
public class ForkLiftCommand {
    /**
     * 提升机号
     */
    private Integer liftNo;
    /**
     * 任务号
     */
    private Short taskNo;
    /**
     * 任务模式
     */
    private Short mode;
    /**
     * 取货数据
     */
    private Short pick;
    /**
     * 放货数据
     */
    private Short put;
    /**
     * 任务确认
     */
    private Short confirm;
    /**
     * 命令是否完成,默认false未完成
     */
    private Boolean complete = false;
}
src/main/java/com/zy/core/model/command/LiftAssignCommand.java
@@ -20,12 +20,10 @@
    /**
     * 命令list
     */
    private List<NyLiftCommand> commands;
    private List<ForkLiftCommand> commands;
    /**
     * 作业类型
     * 1=移托盘;升降机将源站台托盘移到目标站台
     * 2=移小车,升降机移到目标层,等待
     */
    private Short taskMode = 0;
src/main/java/com/zy/core/model/command/LiftCommand.java
@@ -1,6 +1,5 @@
package com.zy.core.model.command;
import com.zy.core.model.protocol.StaProtocol;
import lombok.Data;
src/main/java/com/zy/core/model/command/NyLiftCommand.java
File was deleted
src/main/java/com/zy/core/model/command/NyShuttleHttpCommand.java
@@ -19,7 +19,7 @@
    private NyRequest request;
    //工作号
    private Integer wrkNo;
    private Integer taskNo;
    @Data
    public static class NyRequest {
src/main/java/com/zy/core/model/command/ShuttleAssignCommand.java
@@ -3,25 +3,38 @@
import com.zy.common.model.NavigateNode;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@Data
public class ShuttleAssignCommand {
public class ShuttleAssignCommand implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * 四向穿梭车号
     */
    private Short shuttleNo = 0;
    private Integer shuttleNo = 0;
    /**
     * 设备ID
     */
    private Integer deviceId;
    /**
     * 任务号
     */
    private Short taskNo = 0;
    private Integer taskNo = 0;
    /**
     * 设备工作号
     */
    private Integer deviceTaskNo = 0;
    /**
     * 作业类型
     * 1: 入库
     * 1:  入库
     * 2: 出库
     * 3: 托盘顶升
     * 4: 托盘下降
@@ -31,7 +44,7 @@
     * 8: 后移
     * 9: 充电
     */
    private Short taskMode = 0;
    private Integer taskMode = 0;
    /**
     * 源库位
@@ -46,7 +59,7 @@
    /**
     * 命令list
     */
    private List<NyShuttleHttpCommand> commands = new ArrayList<>();
    private List<ShuttleCommand> commands = new ArrayList<>();
    /**
     * 是否自动,true:自动模式,false:手动模式
@@ -64,4 +77,15 @@
     */
    private List<NavigateNode> nodes;
}
    public List<NavigateNode> getNodesDeepCopy() {
        if (this.nodes == null) {
            return null;
        }
        List<NavigateNode> navigateNodes = new ArrayList<>();
        for (NavigateNode node : nodes) {
            navigateNodes.add(node.clone());
        }
        return navigateNodes;
    }
}
src/main/java/com/zy/core/model/command/ShuttleCommand.java
@@ -1,6 +1,9 @@
package com.zy.core.model.command;
import com.zy.common.model.NavigateNode;
import com.zy.core.enums.ShuttleCommandModeType;
import lombok.Data;
import java.util.List;
/**
 * 四向穿梭车命令报文
@@ -11,91 +14,36 @@
    /**
     * 四向穿梭车号
     */
    private Short shuttleNo = 0;
    private Integer shuttleNo;
    /**
     * 任务号
     */
    private Short taskNo = 0;
    private Integer taskNo = 0;
    /**
     * 作业类型
     * 命令类型
     */
    private Short taskMode = 0;
    private Integer mode = ShuttleCommandModeType.NONE.id;
    /**
     * 控制指令字
     * 目标库位
     */
    private Short commandWord;
    private String targetLocNo;
    /**
     * 启始二维编号
     * 报文内容
     */
    private Short startCodeNum;
    /**
     * 中间二维编号
     */
    private Short middleCodeNum;
    /**
     * 目标二维编号
     */
    private Short distCodeNum;
    /**
     * 起点到目标点的距离长度
     */
    private Integer startToDistDistance;
    /**
     * 中间点到目标点的距离长度
     */
    private Integer middleToDistDistance;
    /**
     * 小车运行方向
     */
    private Short runDirection;
    /**
     * 托盘顶升
     */
    private Short palletLift;
    /**
     * 小车强制移动距离
     */
    private Integer forceMoveDistance;
    /**
     * 充电开关
     */
    private Short chargeSwitch;
    /**
     * 小车IO控制
     */
    private Short IOControl;
    /**
     * 小车运行速度
     */
    private Short runSpeed;
    /**
     * 小车雷达备用
     */
    private Short radarTmp;
    /**
     * 指令结束位
     */
    private Short commandEnd;
    private String body;
    /**
     * 命令是否完成,默认false未完成
     */
    private Boolean complete = false;
    /**
     * 行走命令所占用的节点list
     */
    private List<NavigateNode> nodes;
}
src/main/java/com/zy/core/model/command/ShuttleRedisCommand.java
@@ -11,10 +11,10 @@
public class ShuttleRedisCommand implements Serializable {
    //四向穿梭车号
    private Short shuttleNo;
    private Integer shuttleNo;
    //工作号
    private Short wrkNo;
    private Integer wrkNo;
    //命令执行步序
    private Integer commandStep;
src/main/java/com/zy/core/model/command/SteCommand.java
File was deleted
src/main/java/com/zy/core/model/param/ShuttleMoveLocParam.java
New file
@@ -0,0 +1,20 @@
package com.zy.core.model.param;
import lombok.Data;
@Data
public class ShuttleMoveLocParam {
    private Integer shuttleNo;
    private Integer moveType;
    private Integer startX;
    private Integer targetX;
    private Integer startY;
    private Integer targetY;
}
src/main/java/com/zy/core/model/protocol/CrnError1.java
File was deleted
src/main/java/com/zy/core/model/protocol/CrnError2.java
File was deleted
src/main/java/com/zy/core/model/protocol/CrnError3.java
File was deleted
src/main/java/com/zy/core/model/protocol/CrnError4.java
File was deleted
src/main/java/com/zy/core/model/protocol/CrnError5.java
File was deleted
src/main/java/com/zy/core/model/protocol/CrnError6.java
File was deleted
src/main/java/com/zy/core/model/protocol/CrnProtocol.java
File was deleted
src/main/java/com/zy/core/model/protocol/CrnTemp1.java
File was deleted
src/main/java/com/zy/core/model/protocol/ForkLiftProtocol.java
New file
@@ -0,0 +1,173 @@
package com.zy.core.model.protocol;
import com.core.common.SpringUtils;
import com.zy.asrs.entity.BasLiftErr;
import com.zy.asrs.service.BasLiftErrService;
import com.zy.core.enums.ForkLiftIoModeType;
import com.zy.core.enums.ForkLiftProtocolStatusType;
import com.zy.core.enums.ForkLiftTaskModeType;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
/**
 * 货叉提升机
 */
@Slf4j
@Data
public class ForkLiftProtocol implements Cloneable {
    /**
     * 提升机号
     */
    private Integer liftNo;
    /**
     * 模式0单机 1联机
     */
    private Integer model;
    /**
     * 任务号
     */
    private Integer taskNo = 0;
    /**
     * 任务状态
     */
    private Integer protocolStatus = ForkLiftProtocolStatusType.NONE.id;
    /**
     * 任务状态枚举
     */
    private ForkLiftProtocolStatusType protocolStatusType = ForkLiftProtocolStatusType.NONE;
    /**
     * 任务模式
     */
    private Integer mode = ForkLiftTaskModeType.NONE.id;
    /**
     * 任务模式枚举
     */
    private ForkLiftTaskModeType modeType = ForkLiftTaskModeType.NONE;
    /**
     * 取货数据
     */
    private Integer pick;
    /**
     * 放货数据
     */
    private Integer put;
    /**
     * 出入库模式
     */
    private Integer iOMode = ForkLiftIoModeType.NONE.id;
    /**
     * 出入库模式枚举
     */
    private ForkLiftIoModeType iOModeType = ForkLiftIoModeType.NONE;
    /**
     * 故障码
     */
    private Integer errorCode;
    /**
     * 作业标记
     */
    private Boolean pakMk = false;
    /**
     * 指令下发时间
     */
    private Long sendTime = 0L;
    /**
     * 日志采集时间
     */
    private Long deviceDataLog = System.currentTimeMillis();
    /**
     * 扩展字段
     */
    private Object extend;
    /**
     * 设置任务状态
     */
    public void setProtocolStatus(Integer status) {
        this.protocolStatus = status;
        this.protocolStatusType = ForkLiftProtocolStatusType.get(status);
    }
    /**
     * 设置任务状态
     */
    public void setProtocolStatus(ForkLiftProtocolStatusType status) {
        this.protocolStatus = status.id;
        this.protocolStatusType = status;
    }
    /**
     * 设置任务模式
     */
    public void setMode(Integer mode) {
        this.mode = mode;
        this.modeType = ForkLiftTaskModeType.get(mode);
    }
    /**
     * 设置任务模式
     */
    public void setMode(ForkLiftTaskModeType mode) {
        this.mode = mode.id;
        this.modeType = mode;
    }
    /**
     * 设置出入库模式
     */
    public void setIOMode(Integer ioMode) {
        this.iOMode = ioMode;
        this.iOModeType = ForkLiftIoModeType.get(ioMode);
    }
    /**
     * 设置出入库模式
     */
    public void setIOMode(ForkLiftIoModeType ioMode) {
        this.iOMode = ioMode.id;
        this.iOModeType = ioMode;
    }
    /**
     * 错误码
     */
    public String getErrCode$() {
        if (this.errorCode == null) {
            return "";
        }
        BasLiftErrService basLiftErrService = SpringUtils.getBean(BasLiftErrService.class);
        BasLiftErr basLiftErr = basLiftErrService.selectById(this.errorCode);
        if (basLiftErr == null) {
            return String.valueOf(this.errorCode);
        }
        return basLiftErr.getErrName();
    }
    @Override
    public ForkLiftProtocol clone() {
        try {
            return (ForkLiftProtocol) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
}
src/main/java/com/zy/core/model/protocol/ForkLiftStaProtocol.java
New file
@@ -0,0 +1,49 @@
package com.zy.core.model.protocol;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
/**
 * 提升机站点
 */
@Slf4j
@Data
public class ForkLiftStaProtocol {
    /**
     * 站点号
     */
    private Integer staNo;
    /**
     * 有托盘
     */
    private Boolean hasTray;
    /**
     * 有小车
     */
    private Boolean hasCar;
    /**
     * 任务号
     */
    private Short taskNo;
    /**
     * 层
     */
    private Integer lev;
    /**
     * 站点库位号
     */
    private String locNo;
    /**
     * 提升机号
     */
    private Integer liftNo;
}
src/main/java/com/zy/core/model/protocol/LiftProtocol.java
File was deleted
src/main/java/com/zy/core/model/protocol/LiftStaProtocol.java
@@ -26,36 +26,6 @@
    private Boolean busy;
    /**
     * 前超限
     */
    private Boolean frontOverrun;
    /**
     * 后超限
     */
    private Boolean backOverrun;
    /**
     * 左超限
     */
    private Boolean leftOverrun;
    /**
     * 右超限
     */
    private Boolean rightOverrun;
    /**
     * 超高
     */
    private Boolean overHeight;
    /**
     * 超重
     */
    private Boolean overWeight;
    /**
     * 有托盘
     */
    private Boolean hasTray;
@@ -71,13 +41,9 @@
    private Boolean deviceError;
    /**
     * 当前执行任务号
     * 任务号
     */
    private Short taskNo;
    /**
     * 已完成的任务号
     */
    private Short completeTaskNo;
    /**
     * 层
src/main/java/com/zy/core/model/protocol/NyShuttleProtocol.java
File was deleted
src/main/java/com/zy/core/model/protocol/ShuttleProtocol.java
@@ -1,19 +1,14 @@
package com.zy.core.model.protocol;
import com.core.common.Cools;
import com.core.common.SpringUtils;
import com.zy.asrs.entity.BasDevp;
import com.zy.asrs.entity.BasShuttle;
import com.zy.asrs.entity.BasShuttleErr;
import com.zy.asrs.entity.LocMast;
import com.zy.asrs.service.BasDevpService;
import com.zy.asrs.service.BasShuttleErrService;
import com.zy.asrs.service.BasShuttleService;
import com.zy.asrs.service.LocMastService;
import com.zy.core.News;
import com.zy.core.enums.ShuttleErrorCodeType;
import com.zy.common.utils.RedisUtil;
import com.zy.core.enums.RedisKeyType;
import com.zy.core.enums.ShuttleProtocolStatusType;
import com.zy.core.enums.ShuttleStatusType;
import com.zy.core.model.command.ShuttleAssignCommand;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
@@ -22,22 +17,18 @@
 */
@Slf4j
@Data
public class ShuttleProtocol {
public class ShuttleProtocol implements Cloneable {
    //**********************必须存在属性**********************
    /**
     * 四向穿梭车号
     */
    private Short shuttleNo;
    private Integer shuttleNo;
    /**
     * 任务号
     */
    private Short taskNo = 0;
    /**
     * 任务指令
     */
    private ShuttleAssignCommand assignCommand;
    private Integer taskNo;
    /**
     * 当前小车状态(内部自我维护)
@@ -45,7 +36,7 @@
    private Integer protocolStatus;
    /**
     * 当前小车状态枚举
     * 当前小车作业状态枚举
     */
    private ShuttleProtocolStatusType protocolStatusType;
@@ -60,147 +51,130 @@
    private String locNo;
    /**
     * 小车忙状态位
     * 1: 忙
     * 0: 空闲
     * 小车设备状态
     */
    private Short busyStatus;
    private Integer deviceStatus;
    /**
     * 小车忙状态位枚举
     * 小车模式,0:手动 1:自动
     */
    private ShuttleStatusType busyStatusType;
    private Integer mode;
    /**
     * 当前二维码
     * 0为空
     */
    private Short currentCode;
    private String currentCode;
    /**
     * 电池电量百分比
     * 电池电量
     */
    private Short batteryPower;
    /**
     * 电池温度
     */
    private Integer batteryTemp;
    private String batteryPower;
    /**
     * 错误编号
     */
    private Short errorCode;
    private String errorCode;
    //**********************非必须属性,实际使用中可能存在空值**********************
    /**
     * 错误编号枚举
     * 电池温度
     */
    private ShuttleErrorCodeType errorCodeType;
    private String batteryTemp;
    /**
     * Plc输出状态IO
     * 是否顶升
     */
    private Short plcOutputStatusIO;
    private Boolean hasLift;
    /**
     * Plc输出状态IO-顶升位
     * 是否有托盘
     */
    private Boolean plcOutputLift;
    private Boolean hasPallet;
    /**
     * Plc输出状态IO-换向位
     * 行驶方向
     */
    private Boolean plcOutputTransfer;
    private String runDirection;
    /**
     * Plc输出状态IO-抱闸位
     * 是否为充电状态
     */
    private Boolean plcOutputBrake;
    private Boolean hasCharge;
    /**
     * Plc输出状态IO-充电位
     * 电池电压
     */
    private Boolean plcOutputCharge;
    private Integer batteryVoltage;
    /**
     * 错误信息码
     */
    private Short statusErrorCode;
    //**********************系统自身所需属性**********************
    /**
     * PLC输入状态,目前只有一个状态有效果,托盘雷达1有货,0无货
     */
    private Short plcInputStatus;
    /**
     * 当前或者之前读到的二维码值
     */
    private Short currentOrBeforeCode;
    /**
     * 读到的二维码X方向偏移量
     */
    private Short codeOffsetX;
    /**
     * 读到的二维码Y方向偏移量
     */
    private Short codeOffsetY;
    /**
     * 当前的电压值
     */
    private Integer currentVoltage;
    /**
     * 当前的模拟量值
     */
    private Short currentAnalogValue;
    /**
     * 当前的升降伺服速度
     */
    private Short currentLiftServoSpeed;
    /**
     * 当前的行走伺服速度
     */
    private Short currentMoveServoSpeed;
    /**
     * 当前的升降伺服负载率
     */
    private Short currentLiftServoLoad;
    /**
     * 当前的行走伺服负载率
     */
    private Short currentMoveServoLoad;
    /**
     * 作业标记
     * 作业标记 false表示正在作业
     */
    private Boolean pakMk = true;
    public void setBusyStatus(Short status) {
        this.busyStatus = status;
        this.busyStatusType = ShuttleStatusType.get(status.intValue());
    }
    /**
     * 跑库状态
     */
    private Boolean moveLoc = false;
    public void setBusyStatus(ShuttleStatusType type) {
        this.busyStatus = type.id.shortValue();
        this.busyStatusType = type;
    }
    /**
     * 跑库类型,0:跑轨道,1:跑库位
     */
    private Integer moveType = 0;
    //获取电池电量
    public Short getBatteryPower$() {
        return (short) (this.batteryPower * 0.1);
    }
    /**
     * 跑库X起点
     */
    private Integer xStart = 0;
    //获取电池温度
    public Short getBatteryTemp$() {
        return (short) (this.batteryTemp * 0.1);
    }
    /**
     * 跑库X终点
     */
    private Integer xTarget = 0;
    /**
     * 跑库X当前点位
     */
    private Integer xCurrent = 0;
    /**
     * 跑库Y起点
     */
    private Integer yStart = 0;
    /**
     * 跑库Y终点
     */
    private Integer yTarget = 0;
    /**
     * 跑库Y当前点位
     */
    private Integer yCurrent = 0;
    /**
     * 日志采集时间
     */
    private Long deviceDataLog = System.currentTimeMillis();
    /**
     * 指令下发时间
     */
    private Long sendTime = 0L;
    /**
     * 最近一次在线时间
     */
    private Long lastOnlineTime = System.currentTimeMillis();
    /**
     * 扩展字段
     */
    private Object extend;
    /**
     * 设置小车状态
@@ -218,105 +192,33 @@
        this.protocolStatusType = status;
    }
    /**
     * 设置错误编号
     */
    public void setErrorCode(Short errorCode) {
        this.errorCode = errorCode;
        this.errorCodeType = ShuttleErrorCodeType.get(errorCode.intValue());
    }
    /**
     * 设置错误编号
     */
    public void setErrorCode(ShuttleErrorCodeType type) {
        this.errorCode = type.id.shortValue();
        this.errorCodeType = type;
    }
    // 是否处于空闲待命状态
    public Boolean isIdle() {
        boolean res = this.busyStatusType.equals(ShuttleStatusType.IDLE)
                && this.pakMk.equals(true)
                && this.errorCodeType.equals(ShuttleErrorCodeType.NORMAL)
                && this.taskNo == 0
                && this.protocolStatus.intValue() == ShuttleProtocolStatusType.IDLE.id
                ;
        if (!res) {
            return res;
        } else {
            // 电量
            try {
                Integer chargeLine = SpringUtils.getBean(BasShuttleService.class).selectById(this.shuttleNo).getChargeLine();
                if (chargeLine == null) {
                    return false;
                }
                return this.getBatteryPower$() >= chargeLine;
            } catch (Exception e) {
                News.error("fail", e);
                return false;
    public Integer getTaskNo() {
        RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class);
        if (null != redisUtil) {
            Object o = redisUtil.get(RedisKeyType.SHUTTLE.key + this.shuttleNo);
            if (!Cools.isEmpty(o)) {
                this.taskNo = Integer.parseInt(String.valueOf(o));
            }
        }
        return this.taskNo == null ? 0 : this.taskNo;
    }
    // 是否处于空闲待命状态,传入的taskNo和当前taskNo相同时允许放行
    public Boolean isIdle(Short taskNo) {
        boolean res = this.busyStatusType.equals(ShuttleStatusType.IDLE)
                && this.pakMk.equals(true)
                && this.errorCodeType.equals(ShuttleErrorCodeType.NORMAL)
                && (this.taskNo == 0 || this.taskNo.intValue() == taskNo.intValue())
                && this.protocolStatus.intValue() == ShuttleProtocolStatusType.IDLE.id
                ;
        if (!res) {
            return res;
        } else {
            // 电量
            try {
                Integer chargeLine = SpringUtils.getBean(BasShuttleService.class).selectById(this.shuttleNo).getChargeLine();
                return this.getBatteryPower$() > chargeLine;
            } catch (Exception e) {
                News.error("fail", e);
                return false;
            }
    public synchronized void setSyncTaskNo(Integer taskNo) {
        RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class);
        if (null != redisUtil) {
            redisUtil.set(RedisKeyType.SHUTTLE.key + this.shuttleNo, taskNo);
            this.taskNo = taskNo;
        }
    }
    // 是否满足充电状态
    public Boolean isRequireCharge() {
        if (this.busyStatusType == null || this.pakMk == null || this.errorCodeType == null || this.taskNo == null) {
            return false;
    @Override
    public ShuttleProtocol clone() {
        try {
            return (ShuttleProtocol) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        boolean res = this.busyStatusType.id.intValue() == ShuttleStatusType.IDLE.id.intValue()
                && this.pakMk
                && this.errorCodeType.id.intValue() == ShuttleErrorCodeType.NORMAL.id.intValue()
                && this.taskNo == 0
                && this.protocolStatusType.id == ShuttleProtocolStatusType.IDLE.id
                ;
        if (!res) {
            return res;
        } else {
            // 电量小于阈值或电压小于48V,需要进行充电
            try {
                BasShuttleService shuttleService = SpringUtils.getBean(BasShuttleService.class);
                if (shuttleService == null) {
                    return false;
                }
                BasShuttle basShuttle = shuttleService.selectById(this.shuttleNo);
                if (basShuttle == null) {
                    return false;
                }
                Integer chargeLine = basShuttle.getChargeLine();
                if (chargeLine == null) {
                    return false;
                }
                return this.getBatteryPower$() < chargeLine || this.currentVoltage < 48000;
            } catch (Exception e) {
                News.error("fail", e);
                return false;
            }
        }
        return null;
    }
    //通过当前二维码获取当前库位号
@@ -326,7 +228,7 @@
            return null;
        }
        //源库位(小车当前位置)
        LocMast currentLocMast = locMastService.queryByQrCode(this.currentCode.toString());
        LocMast currentLocMast = locMastService.queryByQrCode(this.currentCode);
        if (currentLocMast == null) {
            return null;
        }
@@ -335,31 +237,14 @@
    public String getStatusErrorCode$() {
        BasShuttleErrService basShuttleErrService = SpringUtils.getBean(BasShuttleErrService.class);
        BasShuttleErr basShuttleErr = basShuttleErrService.queryByCode(this.statusErrorCode.intValue());
        if (this.errorCode == null) {
            return "";
        }
        BasShuttleErr basShuttleErr = basShuttleErrService.queryByCode(Integer.valueOf(this.errorCode));
        if (basShuttleErr == null) {
            return this.statusErrorCode.toString();
            return this.errorCode;
        }
        return basShuttleErr.getErrName();
    }
    public void setCurrentCode(Short currentCode) {
        this.currentCode = currentCode;
        LocMastService locMastService = SpringUtils.getBean(LocMastService.class);
        if (locMastService != null) {
            LocMast locMast = locMastService.queryByQrCode(currentCode.toString());
            if (locMast == null) {
                //查不到库位号,查询是否为站点
                BasDevpService basDevpService = SpringUtils.getBean(BasDevpService.class);
                if (basDevpService != null) {
                    BasDevp basDevp = basDevpService.queryByLocNo(currentCode.toString());
                    if (basDevp != null) {
                        this.locNo = basDevp.getLocNo();
                    }
                }
            }else{
                this.locNo = locMast.getLocNo();
            }
        }
    }
}
src/main/java/com/zy/core/model/protocol/SteProtocol.java
File was deleted
src/main/java/com/zy/core/properties/SlaveProperties.java
@@ -25,15 +25,7 @@
    private List<String> channel = new ArrayList<>();
    private List<CrnSlave> crn = new ArrayList<>();
    private List<SteSlave> ste = new ArrayList<>();
    private List<DevpSlave> devp = new ArrayList<>();
    private List<Devp2Slave> devp2 = new ArrayList<>();
    private List<Devp2Slave> devp3 = new ArrayList<>();
    private List<Slave> barcode = new ArrayList<>();
@@ -45,6 +37,6 @@
    private List<ShuttleSlave> shuttle = new ArrayList<>();
    private List<LiftSlave> lift = new ArrayList<>();
    private List<ForkLiftSlave> forkLift = new ArrayList<>();
}
src/main/java/com/zy/core/thread/ForkLiftThread.java
New file
@@ -0,0 +1,46 @@
package com.zy.core.thread;
import com.zy.common.ExecuteSupport;
import com.zy.core.ThreadHandler;
import com.zy.core.enums.ForkLiftProtocolStatusType;
import com.zy.core.enums.ForkLiftTaskModeType;
import com.zy.core.model.CommandResponse;
import com.zy.core.model.command.ForkLiftCommand;
import com.zy.core.model.protocol.ForkLiftProtocol;
import com.zy.core.model.protocol.ForkLiftStaProtocol;
import java.util.List;
public interface ForkLiftThread extends ThreadHandler {
    ForkLiftProtocol getStatus();//获取提升机状态
    ForkLiftProtocol getStatus(boolean clone);//获取提升机状态
    List<ForkLiftStaProtocol> getForkLiftStaProtocols();
    CommandResponse pickAndPut(ForkLiftCommand command);//取放货指令
    CommandResponse shuttleSwitch(ForkLiftCommand command);//小车换层
    CommandResponse reset(ForkLiftCommand command);//复位
    boolean isIdle();//是否空闲
    boolean isDeviceIdle();//设备是否空闲
    boolean isDeviceIdle(ExecuteSupport support);//设备是否空闲
    boolean setProtocolStatus(ForkLiftProtocolStatusType status);//设置工作状态
    boolean setSyncTaskNo(Integer taskNo);//设置工作号
    int generateDeviceTaskNo(int taskNo, ForkLiftTaskModeType type);//生成硬件设备工作号
    //***************获取命令*****************
    List<ForkLiftCommand> getPickAndPutCommand(Integer taskNo, Integer pick, Integer put);//取放货指令
    List<ForkLiftCommand> getShuttleSwitchCommand(Integer taskNo, Integer originLev, Integer targetLev);//小车换层
}
src/main/java/com/zy/core/thread/LiftThread.java
@@ -1,536 +1,522 @@
package com.zy.core.thread;
import HslCommunication.Core.Types.OperateResult;
import HslCommunication.Core.Types.OperateResultExOne;
import HslCommunication.Profinet.Siemens.SiemensPLCS;
import HslCommunication.Profinet.Siemens.SiemensS7Net;
import com.alibaba.fastjson.JSON;
import com.core.common.DateUtils;
import com.core.common.SpringUtils;
import com.core.exception.CoolException;
import com.zy.asrs.entity.BasLift;
import com.zy.asrs.entity.BasLiftOpt;
import com.zy.asrs.entity.DeviceDataLog;
import com.zy.asrs.mapper.WrkMastMapper;
import com.zy.asrs.service.BasLiftOptService;
import com.zy.asrs.service.BasLiftService;
import com.zy.asrs.service.DeviceDataLogService;
import com.zy.asrs.utils.Utils;
import com.zy.common.utils.RedisUtil;
import com.zy.core.News;
import com.zy.core.ThreadHandler;
import com.zy.core.cache.MessageQueue;
import com.zy.core.cache.OutputQueue;
import com.zy.core.enums.*;
import com.zy.core.model.LiftSlave;
import com.zy.core.model.Task;
import com.zy.core.model.command.*;
import com.zy.core.model.protocol.LiftStaProtocol;
import com.zy.core.model.protocol.LiftProtocol;
import com.zy.core.model.protocol.StaProtocol;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.text.MessageFormat;
import java.util.*;
/**
 * 提升机线程
 */
@Data
@Slf4j
public class LiftThread implements  Runnable, ThreadHandler {
    private SiemensS7Net siemensS7Net;
    private LiftSlave slave;
    private LiftProtocol liftProtocol;
    private RedisUtil redisUtil;
    private List<LiftStaProtocol> liftStaProtocols = new ArrayList<>();
    public LiftThread(LiftSlave slave,RedisUtil redisUtil) {
        this.slave = slave;
        this.redisUtil = redisUtil;
        //初始化站点
        for (LiftSlave.Sta sta : this.slave.getSta()) {
            LiftStaProtocol liftStaProtocol = new LiftStaProtocol();
            liftStaProtocol.setStaNo(sta.getStaNo());//站点号
            liftStaProtocol.setLev(sta.getLev());//站点楼层
            String locNo = Utils.getLocNo(this.slave.getStaRow(), this.slave.getStaBay(), sta.getLev());
            liftStaProtocol.setLocNo(locNo);//站点库位号
            liftStaProtocol.setLiftNo(sta.getLiftNo());//提升机号
            liftStaProtocols.add(liftStaProtocol);
        }
    }
    @Override
    public void run() {
        this.connect();
        while (true) {
            try {
                int step = 1;
                Task task = MessageQueue.poll(SlaveType.Lift, slave.getId());
                if (task != null) {
                    step = task.getStep();
                }
                switch (step) {
                    // 读数据
                    case 1:
                        read();
                        break;
                    // 写入数据
                    case 2:
                        write((NyLiftCommand) task.getData());
                        break;
                    //分配任务
                    case 3:
                        assignWork((LiftAssignCommand) task.getData());
                        break;
                    case 4:
                        write2((HashMap<String, Object>) task.getData());
                    default:
                        break;
                }
                Thread.sleep(500);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    @Override
    public boolean connect() {
        boolean result = false;
        //-------------------------提升机连接方法------------------------//
        siemensS7Net = new SiemensS7Net(SiemensPLCS.S1200, slave.getIp());
        OperateResult connect = siemensS7Net.ConnectServer();
        if(connect.IsSuccess){
            result = true;
            OutputQueue.CRN.offer(MessageFormat.format( "【{0}】提升机plc连接成功 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
            log.info("提升机plc连接成功 ===>> [id:{}] [ip:{}] [port:{}] ", slave.getId(), slave.getIp(), slave.getPort());
        } else {
            OutputQueue.CRN.offer(MessageFormat.format("【{0}】提升机plc连接失败!!! ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
            log.error("提升机plc连接失败!!! ===>> [id:{}] [ip:{}] [port:{}] ", slave.getId(), slave.getIp(), slave.getPort());
        }
        siemensS7Net.ConnectClose();
        //-------------------------提升机连接方法------------------------//
        return result;
    }
    @Override
    public void close() {
        siemensS7Net.ConnectClose();
    }
    private void read() {
        try {
            readStatus();
            //提升机处于运行状态,将标记置为false
            if (liftProtocol.getBusy()) {
                liftProtocol.setPakMk(false);
            }
            //提升机处于未运行、就绪、标记true、有任务号
            if (!liftProtocol.getBusy()
                    && !liftProtocol.getPakMk()
                    && liftProtocol.getTaskNo() != 0) {
                //还有未完成的命令
                executeWork(liftProtocol.getTaskNo());
            }
        } catch (Exception e) {
            OutputQueue.LIFT.offer(MessageFormat.format("【{0}】提升机plc状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
        }
    }
    private void readStatus() {
        try {
            //获取提升机数据
            OperateResultExOne<byte[]> result1 = siemensS7Net.Read("DB82.4.0", (short) 10);
            if (result1.IsSuccess) {
                if (null == liftProtocol) {
                    liftProtocol = new LiftProtocol();
                    liftProtocol.setLiftNo(slave.getId().shortValue());
                }
                //读取4.0-4.7数据
                boolean[] status1 = siemensS7Net.getByteTransform().TransBool(result1.Content, 0, 1);
                //读取5.0-5.7数据
                boolean[] status2 = siemensS7Net.getByteTransform().TransBool(result1.Content, 1, 1);
                //模式
                liftProtocol.setModel(status1[0]);
                //忙闲
                liftProtocol.setBusy(!status1[1]);
                //前超限
                liftProtocol.setFrontOverrun(status1[4]);
                //后超限
                liftProtocol.setBackOverrun(status1[5]);
                //左超限
                liftProtocol.setLeftOverrun(status1[6]);
                //右超限
                liftProtocol.setRightOverrun(status1[7]);
                //超高
                liftProtocol.setOverHeight(status2[0]);
                //超重
                liftProtocol.setOverWeight(status2[1]);
                //有托盘
                liftProtocol.setHasTray(status2[5]);
                //有小车
                liftProtocol.setHasCar(status2[6]);
                //设备故障
                liftProtocol.setDeviceError(status2[7]);
                //任务号
                liftProtocol.setTaskNo(siemensS7Net.getByteTransform().TransInt16(result1.Content, 2));
                //目的地址
                liftProtocol.setDistAddress(siemensS7Net.getByteTransform().TransInt16(result1.Content, 4));
                //已完成任务号
                liftProtocol.setCompleteTaskNo(siemensS7Net.getByteTransform().TransInt16(result1.Content, 6));
                //当前楼层
                short lev = siemensS7Net.getByteTransform().TransInt16(result1.Content, 8);
                if (lev >= 7 && lev <= 9) {
                    lev -= 2;
                } else if (lev >= 12 && lev <= 14) {
                    lev -= 4;
                }
                liftProtocol.setLev(lev);
                //将提升机状态保存至数据库
                BasLiftService liftService = SpringUtils.getBean(BasLiftService.class);
                BasLift basLift = liftService.selectById(liftProtocol.getLiftNo());
                if (basLift == null) {
                    basLift = new BasLift();
                    //提升机号
                    basLift.setLiftNo(slave.getId());
                    liftService.insert(basLift);
                }
                basLift.setStatus(liftProtocol.getProtocolStatus());
                basLift.setWrkNo(liftProtocol.getTaskNo().intValue());
                basLift.setUpdateTime(new Date());
                basLift.setPakMk(liftProtocol.getPakMk());
                basLift.setDeviceStatus(JSON.toJSONString(liftProtocol));
                if (liftService.updateById(basLift)) {
                    OutputQueue.LIFT.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId()));
//                    log.info(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId()));
                }
            }else {
                OutputQueue.LIFT.offer(MessageFormat.format("【{0}】{1}提升机plc状态信息失败", DateUtils.convert(new Date()), slave.getId()));
                throw new CoolException(MessageFormat.format( "提升机plc状态信息失败 ===>> [id:{0}] [ip:{1}] [port:{2}]", slave.getId(), slave.getIp(), slave.getPort()));
            }
            Thread.sleep(200);
            //获取提升机站点数据
            OperateResultExOne<byte[]> result2 = siemensS7Net.Read("DB82.14.0", (short) (10 * liftStaProtocols.size()));
            if (result1.IsSuccess) {
                for (int i = 0; i < slave.getSta().size(); i++) {
                    LiftStaProtocol liftStaProtocol = liftStaProtocols.get(i);
                    int i1 = 0 + (i * 10);
                    int i2 = 1 + (i * 10);
                    //读取x4.0-x4.7数据
                    boolean[] status1 = siemensS7Net.getByteTransform().TransBool(result2.Content, i1, 1);
                    //读取x5.0-x5.7数据
                    boolean[] status2 = siemensS7Net.getByteTransform().TransBool(result2.Content, i2, 1);
                    //模式
                    liftStaProtocol.setModel(status1[0]);
                    //忙闲
                    liftStaProtocol.setBusy(!status1[1]);
                    //有托盘
                    liftStaProtocol.setHasTray(status1[2]);
                    //前超限
                    liftStaProtocol.setFrontOverrun(status1[4]);
                    //后超限
                    liftStaProtocol.setBackOverrun(status1[5]);
                    //左超限
                    liftStaProtocol.setLeftOverrun(status1[6]);
                    //右超限
                    liftStaProtocol.setRightOverrun(status1[7]);
                    //超高
                    liftStaProtocol.setOverHeight(status2[0]);
                    //超重
                    liftStaProtocol.setOverWeight(status2[1]);
                    //有小车
                    liftStaProtocol.setHasCar(status2[6]);
                    //设备故障
                    liftStaProtocol.setDeviceError(status2[7]);
                    //任务号
                    liftStaProtocol.setTaskNo(siemensS7Net.getByteTransform().TransInt16(result2.Content, 2));
                    //已完成任务号
                    liftStaProtocol.setCompleteTaskNo(siemensS7Net.getByteTransform().TransInt16(result2.Content, 6));
                }
            }
            Thread.sleep(100);
            //获取提升机异常数据
            OperateResultExOne<byte[]> result3 = siemensS7Net.Read("DB82.22.0", (short) 2);
            if (result3.IsSuccess) {
                liftProtocol.setErrorCode(siemensS7Net.getByteTransform().TransInt16(result3.Content, 0));//错误码
            }
            if (System.currentTimeMillis() - liftProtocol.getDeviceDataLog() > 1000 * 5) {
                //采集时间超过5s,保存一次数据记录
                //保存数据记录
                DeviceDataLogService deviceDataLogService = SpringUtils.getBean(DeviceDataLogService.class);
                DeviceDataLog deviceDataLog = new DeviceDataLog();
                deviceDataLog.setOriginData(Base64.getEncoder().encodeToString(result1.Content));
                deviceDataLog.setWcsData(JSON.toJSONString(liftProtocol));
                deviceDataLog.setType("lift");
                deviceDataLog.setDeviceNo(liftProtocol.getLiftNo().intValue());
                deviceDataLog.setCreateTime(new Date());
                deviceDataLogService.insert(deviceDataLog);
                //更新采集时间
                liftProtocol.setDeviceDataLog(System.currentTimeMillis());
            }
        } catch (Exception e) {
            OutputQueue.LIFT.offer(MessageFormat.format("【{0}】提升机plc状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
        }
    }
    private boolean write(NyLiftCommand command){
        if (null == command) {
            News.error("提升机写入命令为空");
            return false;
        }
        command.setLiftNo(slave.getId().shortValue());
        short[] array = getCommandArr(command);//获取命令报文
        OperateResult result = siemensS7Net.Write("DB83.0", array);
        if (result != null && result.IsSuccess) {
            liftProtocol.setSendTime(System.currentTimeMillis());//指令下发时间
            News.info("提升机命令下发[id:{}] >>>>> {}", slave.getId(), JSON.toJSON(command));
            OutputQueue.LIFT.offer(MessageFormat.format("【{0}】[id:{1}] >>>>> 命令下发: {2}", DateUtils.convert(new Date()), slave.getId(), JSON.toJSON(command)));
            return true;
        } else {
            OutputQueue.LIFT.offer(MessageFormat.format("【{0}】写入提升机plc数据失败 ===>> [id:{1}] [ip:{2}] [port:{3}],次数:{}", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
            News.error("写入提升机plc数据失败 ===>> [id:{}] [ip:{}] [port:{}]", slave.getId(), slave.getIp(), slave.getPort());
            return false;
        }
    }
    //获取命令报文
    private short[] getCommandArr(NyLiftCommand command) {
        // 开始任务
        short[] array = new short[4];
        if (command.getTaskModel() != null) {
            //任务类型
            array[0] = command.getTaskModel();
        }
        if (command.getSourceSta() != null) {
            //源站台编号
            array[1] = command.getSourceSta();
        }
        if (command.getTargetSta() != null) {
            //目标站台编号
            array[2] = command.getTargetSta();
        }
        if (command.getTaskNo() != null) {
            //任务号
            array[3] = command.getTaskNo();
        }
        return array;
    }
    //分配任务
    private void assignWork(LiftAssignCommand assignCommand) {
        LiftRedisCommand redisCommand = new LiftRedisCommand();
        redisCommand.setLiftNo(assignCommand.getLiftNo());//提升机号
        redisCommand.setWrkNo(assignCommand.getTaskNo());//工作号
        redisCommand.setCommandStep(0);//命令执行步序
        redisCommand.setAssignCommand(assignCommand);//命令
        //任务数据保存到redis
        redisUtil.set(RedisKeyType.LIFT.key + assignCommand.getTaskNo(), JSON.toJSONString(redisCommand));
        liftProtocol.setAssignCommand(assignCommand);
        liftProtocol.setProtocolStatus(LiftProtocolStatusType.WORKING);
        //执行下发任务
        executeWork(assignCommand.getTaskNo());
    }
    //执行任务
    private boolean executeWork(Short wrkNo) {
        //读取redis数据
        if (wrkNo == null) {
            return false;
        }
        if (wrkNo >= 20000 && wrkNo <= 30000) {
            //提升机设备工作号,需要查询对应任务号
            BasLiftOptService basLiftOptService = SpringUtils.getBean(BasLiftOptService.class);
            BasLiftOpt basLiftOpt = basLiftOptService.selectByDeviceWrk(liftProtocol.getTaskNo().toString(), liftProtocol.getLiftNo().intValue());
            if (basLiftOpt != null) {
                wrkNo = basLiftOpt.getWrkNo().shortValue();
            }
        }
        Object o = redisUtil.get(RedisKeyType.LIFT.key + wrkNo);
        if (o == null) {
            return false;
        }
        LiftRedisCommand redisCommand = JSON.parseObject(o.toString(), LiftRedisCommand.class);
        List<NyLiftCommand> commands = redisCommand.getAssignCommand().getCommands();
        //当前步序
        int commandStep = redisCommand.getCommandStep();
        //总步序
        int size = commands.size();
        if (!redisCommand.getLiftNo().equals(liftProtocol.getLiftNo())) {
            return false;
        }
        if (commandStep != 0) {
            //判断上一条指令是否做完
            NyLiftCommand lastCommand = commands.get(commandStep - 1);//上一条指令
            if (!liftProtocol.getBusy() && liftProtocol.getTaskNo().equals(lastCommand.getTaskNo())) {
                //提升机空闲、且提升机工作号与上一条指令工作号相同
                lastCommand.setComplete(true);//标记任务完成
            }
            //任务数据保存到redis
            redisUtil.set(RedisKeyType.LIFT.key + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand));
            if (!lastCommand.getComplete()) {
                //上一条任务未完成,禁止下发命令
                return false;
            }
            //判断是否为最后一条命令且命令执行完成,抛出等待确认状态
            NyLiftCommand endCommand = commands.get(commands.size() - 1);
            if (endCommand.getComplete()) {
                //已执行完成
                //删除redis
                redisUtil.del(RedisKeyType.LIFT.key + redisCommand.getWrkNo());
                //对主线程抛出等待确认状态waiting
                liftProtocol.setProtocolStatus(LiftProtocolStatusType.WAITING);
                News.info("提升机任务执行下发完成执行结束,提升机号={},任务数据={}", redisCommand.getLiftNo(), JSON.toJSON(redisCommand));
            }
        }
        //取出命令
        NyLiftCommand command = commands.get(commandStep);
        //下发命令
        if (!write(command)) {
            News.error("提升机命令下发失败,提升机号={},任务数据={}", command.getLiftNo(), JSON.toJSON(command));
            return false;
        }
        liftProtocol.setProtocolStatus(LiftProtocolStatusType.WORKING);
        News.info("提升机命令下发成功,提升机号={},任务数据={}", command.getLiftNo(), JSON.toJSON(command));
        //将标记置为true(防止重发)
        liftProtocol.setPakMk(true);
        //保存数据到数据库做流水
        BasLiftOptService liftOptService = SpringUtils.getBean(BasLiftOptService.class);
        if (liftOptService != null) {
            short[] commandArr = getCommandArr(command);//获取命令报文
            BasLiftOpt opt = new BasLiftOpt(
                    redisCommand.getWrkNo().intValue(),
                    liftProtocol.getLiftNo().intValue(),
                    new Date(),
                    null,
                    null,
                    null,
                    JSON.toJSONString(command),
                    JSON.toJSONString(liftProtocol)
            );
            opt.setDeviceWrk(command.getTaskNo().toString());//设备工作号
            liftOptService.insert(opt);
        }
        //更新redis数据
        //步序增加
        commandStep++;
        redisCommand.setCommandStep(commandStep);
        //任务数据保存到redis
        redisUtil.set(RedisKeyType.LIFT.key + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand));
//        //判断数据是否执行完成
//        if (commandStep < size - 1) {
//            //更新redis数据
//            //步序增加
//            commandStep++;
//            redisCommand.setCommandStep(commandStep);
//package com.zy.core.thread;
//
//import HslCommunication.Core.Types.OperateResult;
//import HslCommunication.Core.Types.OperateResultExOne;
//import HslCommunication.Profinet.Siemens.SiemensPLCS;
//import HslCommunication.Profinet.Siemens.SiemensS7Net;
//import com.alibaba.fastjson.JSON;
//import com.core.common.DateUtils;
//import com.core.common.SpringUtils;
//import com.core.exception.CoolException;
//import com.zy.asrs.entity.BasLift;
//import com.zy.asrs.entity.BasLiftOpt;
//import com.zy.asrs.entity.DeviceDataLog;
//import com.zy.asrs.mapper.WrkMastMapper;
//import com.zy.asrs.service.BasLiftOptService;
//import com.zy.asrs.service.BasLiftService;
//import com.zy.asrs.service.DeviceDataLogService;
//import com.zy.asrs.utils.Utils;
//import com.zy.common.utils.RedisUtil;
//import com.zy.core.News;
//import com.zy.core.ThreadHandler;
//import com.zy.core.cache.MessageQueue;
//import com.zy.core.cache.OutputQueue;
//import com.zy.core.enums.*;
//import com.zy.core.model.LiftSlave;
//import com.zy.core.model.Task;
//import com.zy.core.model.command.*;
//import com.zy.core.model.protocol.LiftStaProtocol;
//import com.zy.core.model.protocol.LiftProtocol;
//import com.zy.core.model.protocol.StaProtocol;
//import lombok.Data;
//import lombok.extern.slf4j.Slf4j;
//
//import java.text.MessageFormat;
//import java.util.*;
//
///**
// * 提升机线程
// */
//@Data
//@Slf4j
//public class LiftThread implements  Runnable, ThreadHandler {
//
//    private SiemensS7Net siemensS7Net;
//    private LiftSlave slave;
//    private LiftProtocol liftProtocol;
//    private RedisUtil redisUtil;
//    private List<LiftStaProtocol> liftStaProtocols = new ArrayList<>();
//
//    public LiftThread(LiftSlave slave,RedisUtil redisUtil) {
//        this.slave = slave;
//        this.redisUtil = redisUtil;
//
//        //初始化站点
//        for (LiftSlave.Sta sta : this.slave.getSta()) {
//            LiftStaProtocol liftStaProtocol = new LiftStaProtocol();
//            liftStaProtocol.setStaNo(sta.getStaNo());//站点号
//            liftStaProtocol.setLev(sta.getLev());//站点楼层
//            String locNo = Utils.getLocNo(this.slave.getStaRow(), this.slave.getStaBay(), sta.getLev());
//            liftStaProtocol.setLocNo(locNo);//站点库位号
//            liftStaProtocol.setLiftNo(sta.getLiftNo());//提升机号
//            liftStaProtocols.add(liftStaProtocol);
//        }
//
//    }
//
//    @Override
//    public void run() {
//        this.connect();
//        while (true) {
//            try {
//                int step = 1;
//                Task task = MessageQueue.poll(SlaveType.Lift, slave.getId());
//                if (task != null) {
//                    step = task.getStep();
//                }
//                switch (step) {
//                    // 读数据
//                    case 1:
//                        read();
//                        break;
//                    // 写入数据
//                    case 2:
//                        write((NyLiftCommand) task.getData());
//                        break;
//                    //分配任务
//                    case 3:
//                        assignWork((LiftAssignCommand) task.getData());
//                        break;
//                    case 4:
//                        write2((HashMap<String, Object>) task.getData());
//                    default:
//                        break;
//                }
//                Thread.sleep(500);
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//        }
//    }
//
//    @Override
//    public boolean connect() {
//        boolean result = false;
//        //-------------------------提升机连接方法------------------------//
//        siemensS7Net = new SiemensS7Net(SiemensPLCS.S1200, slave.getIp());
//        OperateResult connect = siemensS7Net.ConnectServer();
//        if(connect.IsSuccess){
//            result = true;
//            OutputQueue.CRN.offer(MessageFormat.format( "【{0}】提升机plc连接成功 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
//            log.info("提升机plc连接成功 ===>> [id:{}] [ip:{}] [port:{}] ", slave.getId(), slave.getIp(), slave.getPort());
//        } else {
//            OutputQueue.CRN.offer(MessageFormat.format("【{0}】提升机plc连接失败!!! ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
//            log.error("提升机plc连接失败!!! ===>> [id:{}] [ip:{}] [port:{}] ", slave.getId(), slave.getIp(), slave.getPort());
//        }
//        siemensS7Net.ConnectClose();
//        //-------------------------提升机连接方法------------------------//
//        return result;
//    }
//
//    @Override
//    public void close() {
//        siemensS7Net.ConnectClose();
//    }
//
//    private void read() {
//        try {
//            readStatus();
//
//            //提升机处于运行状态,将标记置为false
//            if (liftProtocol.getBusy()) {
//                liftProtocol.setPakMk(false);
//            }
//
//            //提升机处于未运行、就绪、标记true、有任务号
//            if (!liftProtocol.getBusy()
//                    && !liftProtocol.getPakMk()
//                    && liftProtocol.getTaskNo() != 0) {
//                //还有未完成的命令
//                executeWork(liftProtocol.getTaskNo());
//            }
//        } catch (Exception e) {
//            OutputQueue.LIFT.offer(MessageFormat.format("【{0}】提升机plc状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
//        }
//    }
//
//    private void readStatus() {
//        try {
//            //获取提升机数据
//            OperateResultExOne<byte[]> result1 = siemensS7Net.Read("DB82.4.0", (short) 10);
//            if (result1.IsSuccess) {
//                if (null == liftProtocol) {
//                    liftProtocol = new LiftProtocol();
//                    liftProtocol.setLiftNo(slave.getId().shortValue());
//                }
//                //读取4.0-4.7数据
//                boolean[] status1 = siemensS7Net.getByteTransform().TransBool(result1.Content, 0, 1);
//                //读取5.0-5.7数据
//                boolean[] status2 = siemensS7Net.getByteTransform().TransBool(result1.Content, 1, 1);
//                //模式
//                liftProtocol.setModel(status1[0]);
//                //忙闲
//                liftProtocol.setBusy(!status1[1]);
//                //前超限
//                liftProtocol.setFrontOverrun(status1[4]);
//                //后超限
//                liftProtocol.setBackOverrun(status1[5]);
//                //左超限
//                liftProtocol.setLeftOverrun(status1[6]);
//                //右超限
//                liftProtocol.setRightOverrun(status1[7]);
//                //超高
//                liftProtocol.setOverHeight(status2[0]);
//                //超重
//                liftProtocol.setOverWeight(status2[1]);
//                //有托盘
//                liftProtocol.setHasTray(status2[5]);
//                //有小车
//                liftProtocol.setHasCar(status2[6]);
//                //设备故障
//                liftProtocol.setDeviceError(status2[7]);
//                //任务号
//                liftProtocol.setTaskNo(siemensS7Net.getByteTransform().TransInt16(result1.Content, 2));
//                //目的地址
//                liftProtocol.setDistAddress(siemensS7Net.getByteTransform().TransInt16(result1.Content, 4));
//                //已完成任务号
//                liftProtocol.setCompleteTaskNo(siemensS7Net.getByteTransform().TransInt16(result1.Content, 6));
//                //当前楼层
//                short lev = siemensS7Net.getByteTransform().TransInt16(result1.Content, 8);
//                if (lev >= 7 && lev <= 9) {
//                    lev -= 2;
//                } else if (lev >= 12 && lev <= 14) {
//                    lev -= 4;
//                }
//                liftProtocol.setLev(lev);
//
//                //将提升机状态保存至数据库
//                BasLiftService liftService = SpringUtils.getBean(BasLiftService.class);
//                BasLift basLift = liftService.selectById(liftProtocol.getLiftNo());
//                if (basLift == null) {
//                    basLift = new BasLift();
//                    //提升机号
//                    basLift.setLiftNo(slave.getId());
//                    liftService.insert(basLift);
//                }
//                basLift.setStatus(liftProtocol.getProtocolStatus());
//                basLift.setWrkNo(liftProtocol.getTaskNo().intValue());
//                basLift.setUpdateTime(new Date());
//                basLift.setPakMk(liftProtocol.getPakMk());
//                basLift.setDeviceStatus(JSON.toJSONString(liftProtocol));
//                if (liftService.updateById(basLift)) {
//                    OutputQueue.LIFT.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId()));
////                    log.info(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId()));
//                }
//            }else {
//                OutputQueue.LIFT.offer(MessageFormat.format("【{0}】{1}提升机plc状态信息失败", DateUtils.convert(new Date()), slave.getId()));
//                throw new CoolException(MessageFormat.format( "提升机plc状态信息失败 ===>> [id:{0}] [ip:{1}] [port:{2}]", slave.getId(), slave.getIp(), slave.getPort()));
//            }
//            Thread.sleep(200);
//
//            //获取提升机站点数据
//            OperateResultExOne<byte[]> result2 = siemensS7Net.Read("DB82.14.0", (short) (10 * liftStaProtocols.size()));
//            if (result1.IsSuccess) {
//                for (int i = 0; i < slave.getSta().size(); i++) {
//                    LiftStaProtocol liftStaProtocol = liftStaProtocols.get(i);
//                    int i1 = 0 + (i * 10);
//                    int i2 = 1 + (i * 10);
//                    //读取x4.0-x4.7数据
//                    boolean[] status1 = siemensS7Net.getByteTransform().TransBool(result2.Content, i1, 1);
//                    //读取x5.0-x5.7数据
//                    boolean[] status2 = siemensS7Net.getByteTransform().TransBool(result2.Content, i2, 1);
//                    //模式
//                    liftStaProtocol.setModel(status1[0]);
//                    //忙闲
//                    liftStaProtocol.setBusy(!status1[1]);
//                    //有托盘
//                    liftStaProtocol.setHasTray(status1[2]);
//                    //有小车
//                    liftStaProtocol.setHasCar(status2[6]);
//                    //设备故障
//                    liftStaProtocol.setDeviceError(status2[7]);
//                    //任务号
//                    liftStaProtocol.setTaskNo(siemensS7Net.getByteTransform().TransInt16(result2.Content, 2));
//                }
//            }
//
//            Thread.sleep(100);
//            //获取提升机异常数据
//            OperateResultExOne<byte[]> result3 = siemensS7Net.Read("DB82.22.0", (short) 2);
//            if (result3.IsSuccess) {
//                liftProtocol.setErrorCode(siemensS7Net.getByteTransform().TransInt16(result3.Content, 0));//错误码
//            }
//
//            if (System.currentTimeMillis() - liftProtocol.getDeviceDataLog() > 1000 * 5) {
//                //采集时间超过5s,保存一次数据记录
//                //保存数据记录
//                DeviceDataLogService deviceDataLogService = SpringUtils.getBean(DeviceDataLogService.class);
//                DeviceDataLog deviceDataLog = new DeviceDataLog();
//                deviceDataLog.setOriginData(Base64.getEncoder().encodeToString(result1.Content));
//                deviceDataLog.setWcsData(JSON.toJSONString(liftProtocol));
//                deviceDataLog.setType("lift");
//                deviceDataLog.setDeviceNo(liftProtocol.getLiftNo().intValue());
//                deviceDataLog.setCreateTime(new Date());
//                deviceDataLogService.insert(deviceDataLog);
//
//                //更新采集时间
//                liftProtocol.setDeviceDataLog(System.currentTimeMillis());
//            }
//
//        } catch (Exception e) {
//            OutputQueue.LIFT.offer(MessageFormat.format("【{0}】提升机plc状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
//        }
//    }
//
//    private boolean write(NyLiftCommand command){
//        if (null == command) {
//            News.error("提升机写入命令为空");
//            return false;
//        }
//
//        command.setLiftNo(slave.getId().shortValue());
//        short[] array = getCommandArr(command);//获取命令报文
//
//        OperateResult result = siemensS7Net.Write("DB83.0", array);
//        if (result != null && result.IsSuccess) {
//            liftProtocol.setSendTime(System.currentTimeMillis());//指令下发时间
//            News.info("提升机命令下发[id:{}] >>>>> {}", slave.getId(), JSON.toJSON(command));
//            OutputQueue.LIFT.offer(MessageFormat.format("【{0}】[id:{1}] >>>>> 命令下发: {2}", DateUtils.convert(new Date()), slave.getId(), JSON.toJSON(command)));
//            return true;
//        } else {
//            OutputQueue.LIFT.offer(MessageFormat.format("【{0}】写入提升机plc数据失败 ===>> [id:{1}] [ip:{2}] [port:{3}],次数:{}", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
//            News.error("写入提升机plc数据失败 ===>> [id:{}] [ip:{}] [port:{}]", slave.getId(), slave.getIp(), slave.getPort());
//            return false;
//        }
//    }
//
//    //获取命令报文
//    private short[] getCommandArr(NyLiftCommand command) {
//        // 开始任务
//        short[] array = new short[4];
//        if (command.getTaskModel() != null) {
//            //任务类型
//            array[0] = command.getTaskModel();
//        }
//        if (command.getSourceSta() != null) {
//            //源站台编号
//            array[1] = command.getSourceSta();
//        }
//        if (command.getTargetSta() != null) {
//            //目标站台编号
//            array[2] = command.getTargetSta();
//        }
//        if (command.getTaskNo() != null) {
//            //任务号
//            array[3] = command.getTaskNo();
//        }
//        return array;
//    }
//
//    //分配任务
//    private void assignWork(LiftAssignCommand assignCommand) {
//        LiftRedisCommand redisCommand = new LiftRedisCommand();
//        redisCommand.setLiftNo(assignCommand.getLiftNo());//提升机号
//        redisCommand.setWrkNo(assignCommand.getTaskNo());//工作号
//        redisCommand.setCommandStep(0);//命令执行步序
//        redisCommand.setAssignCommand(assignCommand);//命令
//        //任务数据保存到redis
//        redisUtil.set(RedisKeyType.LIFT.key + assignCommand.getTaskNo(), JSON.toJSONString(redisCommand));
//        liftProtocol.setAssignCommand(assignCommand);
//        liftProtocol.setProtocolStatus(LiftProtocolStatusType.WORKING);
//        //执行下发任务
//        executeWork(assignCommand.getTaskNo());
//    }
//
//    //执行任务
//    private boolean executeWork(Short wrkNo) {
//        //读取redis数据
//        if (wrkNo == null) {
//            return false;
//        }
//
//        if (wrkNo >= 20000 && wrkNo <= 30000) {
//            //提升机设备工作号,需要查询对应任务号
//            BasLiftOptService basLiftOptService = SpringUtils.getBean(BasLiftOptService.class);
//            BasLiftOpt basLiftOpt = basLiftOptService.selectByDeviceWrk(liftProtocol.getTaskNo().toString(), liftProtocol.getLiftNo().intValue());
//            if (basLiftOpt != null) {
//                wrkNo = basLiftOpt.getWrkNo().shortValue();
//            }
//        }
//
//        Object o = redisUtil.get(RedisKeyType.LIFT.key + wrkNo);
//        if (o == null) {
//            return false;
//        }
//        LiftRedisCommand redisCommand = JSON.parseObject(o.toString(), LiftRedisCommand.class);
//        List<NyLiftCommand> commands = redisCommand.getAssignCommand().getCommands();
//        //当前步序
//        int commandStep = redisCommand.getCommandStep();
//        //总步序
//        int size = commands.size();
//
//        if (!redisCommand.getLiftNo().equals(liftProtocol.getLiftNo())) {
//            return false;
//        }
//
//        if (commandStep != 0) {
//            //判断上一条指令是否做完
//            NyLiftCommand lastCommand = commands.get(commandStep - 1);//上一条指令
//            if (!liftProtocol.getBusy() && liftProtocol.getTaskNo().equals(lastCommand.getTaskNo())) {
//                //提升机空闲、且提升机工作号与上一条指令工作号相同
//                lastCommand.setComplete(true);//标记任务完成
//            }
//
//            //任务数据保存到redis
//            redisUtil.set(RedisKeyType.LIFT.key + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand));
//        }else {
//            //已执行完成
//            //删除redis
//            redisUtil.del(RedisKeyType.LIFT.key + redisCommand.getWrkNo());
//
//            //对主线程抛出等待确认状态waiting
//            liftProtocol.setProtocolStatus(LiftProtocolStatusType.WAITING);
//            News.info("提升机任务执行下发完成等待执行结束,提升机号={},任务数据={}", command.getLiftNo(), JSON.toJSON(command));
//            if (!lastCommand.getComplete()) {
//                //上一条任务未完成,禁止下发命令
//                return false;
//            }
//
//            //判断是否为最后一条命令且命令执行完成,抛出等待确认状态
//            NyLiftCommand endCommand = commands.get(commands.size() - 1);
//            if (endCommand.getComplete()) {
//                //已执行完成
//                //删除redis
//                redisUtil.del(RedisKeyType.LIFT.key + redisCommand.getWrkNo());
//
//                //对主线程抛出等待确认状态waiting
//                liftProtocol.setProtocolStatus(LiftProtocolStatusType.WAITING);
//                News.info("提升机任务执行下发完成执行结束,提升机号={},任务数据={}", redisCommand.getLiftNo(), JSON.toJSON(redisCommand));
//            }
//
//        }
        if (redisCommand.getAssignCommand().getTaskMode() == NyLiftTaskModelType.RESET.id.shortValue()) {
            //复位命令
            //工作号清零
            liftProtocol.setTaskNo((short) 0);
            //令牌清零
            liftProtocol.setToken(0);
            //设置提升机为空闲状态
            liftProtocol.setProtocolStatus(LiftProtocolStatusType.IDLE);
            //任务指令清零
            liftProtocol.setAssignCommand(null);
        }
        return true;
    }
    //给提升机写入进出状态
    private void write2(HashMap<String,Object> data) {
//        //出
//        status = true;
//        //进
//        status = false;
        int lev = Integer.parseInt(data.get("lev").toString());
        boolean status = Boolean.parseBoolean(data.get("status").toString());
        ArrayList<String> list = new ArrayList<String>(){{
            add("83.8.0");
            add("83.8.1");
            add("83.8.2");
            add("83.8.3");
            add("83.8.4");
            add("83.8.5");
            add("83.8.6");
            add("83.8.7");
            add("83.9.0");
            add("83.9.1");
        }};
        OperateResult result = siemensS7Net.Write("DB" + list.get(lev - 1), status);
        if (result != null && result.IsSuccess) {
            News.info("提升机命令下发[id:{}]", slave.getId());
        } else {
            News.error("写入提升机plc数据失败 ===>> [id:{}] [ip:{}] [port:{}]", slave.getId(), slave.getIp(), slave.getPort());
        }
    }
    /******************************************************************************************/
    /**************************************** 测试专用 *****************************************/
    /*****************************************************************************************/
    public static void main(String[] args) throws InterruptedException {
        LiftSlave slave = new LiftSlave();
        slave.setId(1);
        slave.setIp("192.168.4.24");
        slave.setPort(502);
//        LiftThread thread = new LiftThread(slave,);
//        thread.connect();
//        thread.readStatus();
//
//        LiftCommand command = new LiftCommand();
//        command.setRun((short) 1);
//        command.setDistPosition((short) 12);
//        command.setSpeed((short) 300);
//        command.setHeight2((short) 100);
//        command.setHeight3((short) 200);
//        command.setHeight4((short) 303);
//        command.setLiftLock(true);
//        thread.write(command);
    }
}
//        //取出命令
//        NyLiftCommand command = commands.get(commandStep);
//
//        //下发命令
//        if (!write(command)) {
//            News.error("提升机命令下发失败,提升机号={},任务数据={}", command.getLiftNo(), JSON.toJSON(command));
//            return false;
//        }
//
//        liftProtocol.setProtocolStatus(LiftProtocolStatusType.WORKING);
//        News.info("提升机命令下发成功,提升机号={},任务数据={}", command.getLiftNo(), JSON.toJSON(command));
//
//        //将标记置为true(防止重发)
//        liftProtocol.setPakMk(true);
//
//        //保存数据到数据库做流水
//        BasLiftOptService liftOptService = SpringUtils.getBean(BasLiftOptService.class);
//        if (liftOptService != null) {
//            short[] commandArr = getCommandArr(command);//获取命令报文
//            BasLiftOpt opt = new BasLiftOpt(
//                    redisCommand.getWrkNo().intValue(),
//                    liftProtocol.getLiftNo().intValue(),
//                    new Date(),
//                    null,
//                    null,
//                    null,
//                    JSON.toJSONString(command),
//                    JSON.toJSONString(liftProtocol)
//            );
//            opt.setDeviceWrk(command.getTaskNo().toString());//设备工作号
//            liftOptService.insert(opt);
//        }
//
//        //更新redis数据
//        //步序增加
//        commandStep++;
//        redisCommand.setCommandStep(commandStep);
//        //任务数据保存到redis
//        redisUtil.set(RedisKeyType.LIFT.key + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand));
//
////        //判断数据是否执行完成
////        if (commandStep < size - 1) {
////            //更新redis数据
////            //步序增加
////            commandStep++;
////            redisCommand.setCommandStep(commandStep);
////            //任务数据保存到redis
////            redisUtil.set(RedisKeyType.LIFT.key + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand));
////        }else {
////            //已执行完成
////            //删除redis
////            redisUtil.del(RedisKeyType.LIFT.key + redisCommand.getWrkNo());
////
////            //对主线程抛出等待确认状态waiting
////            liftProtocol.setProtocolStatus(LiftProtocolStatusType.WAITING);
////            News.info("提升机任务执行下发完成等待执行结束,提升机号={},任务数据={}", command.getLiftNo(), JSON.toJSON(command));
////        }
//
//        if (redisCommand.getAssignCommand().getTaskMode() == NyLiftTaskModelType.RESET.id.shortValue()) {
//            //复位命令
//            //工作号清零
//            liftProtocol.setTaskNo((short) 0);
//            //令牌清零
//            liftProtocol.setToken(0);
//            //设置提升机为空闲状态
//            liftProtocol.setProtocolStatus(LiftProtocolStatusType.IDLE);
//            //任务指令清零
//            liftProtocol.setAssignCommand(null);
//        }
//
//        return true;
//    }
//
//    //给提升机写入进出状态
//    private void write2(HashMap<String,Object> data) {
////        //出
////        status = true;
////        //进
////        status = false;
//        int lev = Integer.parseInt(data.get("lev").toString());
//        boolean status = Boolean.parseBoolean(data.get("status").toString());
//
//        ArrayList<String> list = new ArrayList<String>(){{
//            add("83.8.0");
//            add("83.8.1");
//            add("83.8.2");
//            add("83.8.3");
//            add("83.8.4");
//            add("83.8.5");
//            add("83.8.6");
//            add("83.8.7");
//            add("83.9.0");
//            add("83.9.1");
//        }};
//        OperateResult result = siemensS7Net.Write("DB" + list.get(lev - 1), status);
//        if (result != null && result.IsSuccess) {
//            News.info("提升机命令下发[id:{}]", slave.getId());
//        } else {
//            News.error("写入提升机plc数据失败 ===>> [id:{}] [ip:{}] [port:{}]", slave.getId(), slave.getIp(), slave.getPort());
//        }
//    }
//
//    /******************************************************************************************/
//    /**************************************** 测试专用 *****************************************/
//    /*****************************************************************************************/
//    public static void main(String[] args) throws InterruptedException {
//        LiftSlave slave = new LiftSlave();
//        slave.setId(1);
//        slave.setIp("192.168.4.24");
//        slave.setPort(502);
////        LiftThread thread = new LiftThread(slave,);
////        thread.connect();
////        thread.readStatus();
////
////        LiftCommand command = new LiftCommand();
////        command.setRun((short) 1);
////        command.setDistPosition((short) 12);
////        command.setSpeed((short) 300);
////        command.setHeight2((short) 100);
////        command.setHeight3((short) 200);
////        command.setHeight4((short) 303);
////        command.setLiftLock(true);
////        thread.write(command);
//
//    }
//
//}
src/main/java/com/zy/core/thread/NyShuttleThread.java
File was deleted
src/main/java/com/zy/core/thread/ShuttleThread.java
@@ -1,1281 +1,74 @@
package com.zy.core.thread;
import HslCommunication.Core.Transfer.DataFormat;
import HslCommunication.Core.Types.OperateResult;
import HslCommunication.Core.Types.OperateResultExOne;
import HslCommunication.ModBus.ModbusTcpNet;
import com.alibaba.fastjson.JSON;
import com.core.common.DateUtils;
import com.core.common.SpringUtils;
import com.core.exception.CoolException;
import com.zy.asrs.entity.*;
import com.zy.asrs.service.*;
import com.zy.asrs.utils.Utils;
import com.zy.common.model.NavigateNode;
import com.zy.common.model.enums.NavigationMapType;
import com.zy.common.utils.*;
import com.zy.core.News;
import com.zy.core.ThreadHandler;
import com.zy.core.cache.MessageQueue;
import com.zy.core.cache.OutputQueue;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.*;
import com.zy.core.model.ShuttleSlave;
import com.zy.core.model.Task;
import com.zy.core.model.command.*;
import com.zy.core.model.protocol.LiftProtocol;
import com.zy.core.model.protocol.ShuttleProtocol;
import com.zy.core.model.protocol.StaProtocol;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import com.zy.common.ExecuteSupport;
import com.zy.common.model.NavigateNode;
import com.zy.core.ThreadHandler;
import com.zy.core.enums.ShuttleProtocolStatusType;
import com.zy.core.enums.ShuttleTaskNoType;
import com.zy.core.model.CommandResponse;
import com.zy.core.model.command.ShuttleCommand;
import com.zy.core.model.param.ShuttleMoveLocParam;
import com.zy.core.model.protocol.ShuttleProtocol;
import java.util.List;
/**
 * 四向穿梭车线程
 */
@Data
@Slf4j
public class ShuttleThread implements  Runnable, ThreadHandler {
public interface ShuttleThread extends ThreadHandler {
    private ModbusTcpNet modbusTcpNet;
    private ShuttleSlave slave;
    private ShuttleProtocol shuttleProtocol;
    private RedisUtil redisUtil;
    ShuttleProtocol getStatus(boolean clone);//获取四向穿梭车状态
    public ShuttleThread(ShuttleSlave slave,RedisUtil redisUtil) {
        this.slave = slave;
        this.redisUtil = redisUtil;
    }
    ShuttleProtocol getStatus();//获取四向穿梭车状态-默认clone
    @Override
    public void run() {
        this.connect();
        while (true) {
            try {
                int step = 1;
                Task task = MessageQueue.poll(SlaveType.Shuttle, slave.getId());
                if (task != null) {
                    step = task.getStep();
                }
                switch (step) {
                    // 读数据
                    case 1:
                        read();
                        break;
                    // 写入数据
                    case 2:
                        write((ShuttleCommand) task.getData());
                        break;
                    //下发任务
                    case 3:
                        assignWork((ShuttleAssignCommand) task.getData());
                        break;
                    default:
                        break;
                }
                Thread.sleep(500);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    CommandResponse movePath(List<NavigateNode> nodes, Integer taskNo);//路径下发
    @Override
    public boolean connect() {
        boolean result = false;
        //-------------------------四向穿梭车连接方法------------------------//
        modbusTcpNet = new ModbusTcpNet(slave.getIp(), slave.getPort(), (byte) 0x01);
        // 当你需要指定格式的数据解析时,就需要设置下面的这个信息
        modbusTcpNet.setDataFormat(DataFormat.ABCD);
        OperateResult connect = modbusTcpNet.ConnectServer();
        if(connect.IsSuccess){
            result = true;
            OutputQueue.CRN.offer(MessageFormat.format( "【{0}】四向穿梭车plc连接成功 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
            log.info("四向穿梭车plc连接成功 ===>> [id:{}] [ip:{}] [port:{}] ", slave.getId(), slave.getIp(), slave.getPort());
        } else {
            OutputQueue.CRN.offer(MessageFormat.format("【{0}】四向穿梭车plc连接失败!!! ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
            log.error("四向穿梭车plc连接失败!!! ===>> [id:{}] [ip:{}] [port:{}] ", slave.getId(), slave.getIp(), slave.getPort());
        }
        modbusTcpNet.ConnectClose();
        //-------------------------四向穿梭车连接方法------------------------//
        return result;
    }
    CommandResponse move(ShuttleCommand command);//移动
    @Override
    public void close() {
        modbusTcpNet.ConnectClose();
    }
    CommandResponse lift(ShuttleCommand command);//顶升
    private void read() {
        try {
            readStatus();
            //四向穿梭车空闲、有任务、标记为true、存在任务指令,需要执行任务的下一条指令
            if (shuttleProtocol.getBusyStatusType() == ShuttleStatusType.IDLE
                    && shuttleProtocol.getTaskNo() != 0
                    && shuttleProtocol.getPakMk()) {
                //执行下一步指令
                executeWork(shuttleProtocol.getTaskNo());
            }
        } catch (Exception e) {
            e.printStackTrace();
            OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车plc状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
            initShuttle();
        }
    }
    CommandResponse charge(ShuttleCommand command);//充电开关
    private void readStatus() {
        try {
            OperateResultExOne<byte[]> result = modbusTcpNet.Read("200", (short) 17);
            if (result.IsSuccess) {
                if (null == shuttleProtocol) {
                    shuttleProtocol = new ShuttleProtocol();
                    shuttleProtocol.setShuttleNo(slave.getId().shortValue());
                    shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.IDLE);
                }
    CommandResponse reset(ShuttleCommand command);//复位开关
                //----------读取四向穿梭车状态-----------
                //获取数据
                byte[] content = result.Content;
                //小车忙状态位
                shuttleProtocol.setBusyStatus(modbusTcpNet.getByteTransform().TransInt16(content,0));
                //当前二维码
                shuttleProtocol.setCurrentCode(modbusTcpNet.getByteTransform().TransInt16(content,2));
                //电池电量百分比
                shuttleProtocol.setBatteryPower(modbusTcpNet.getByteTransform().TransInt16(content,4));
                //电池温度
                shuttleProtocol.setBatteryTemp(modbusTcpNet.getByteTransform().TransUInt16(content, 6));
                //错误编号
                shuttleProtocol.setErrorCode(modbusTcpNet.getByteTransform().TransInt16(content,8));
                //Plc输出状态IO
                int plcOutIo = modbusTcpNet.getByteTransform().TransUInt16(content, 10);
                int[] plcOutIos = CommonUtils.byteToBits((byte) plcOutIo);
                shuttleProtocol.setPlcOutputLift(plcOutIos[1] == 1);
                shuttleProtocol.setPlcOutputTransfer(plcOutIos[2] == 1);
                shuttleProtocol.setPlcOutputBrake(plcOutIos[3] == 1);
                shuttleProtocol.setPlcOutputCharge(plcOutIos[4] == 1);
                shuttleProtocol.setPlcOutputStatusIO(modbusTcpNet.getByteTransform().TransInt16(content, 10));
                //错误信息码
                shuttleProtocol.setStatusErrorCode(modbusTcpNet.getByteTransform().TransInt16(content,12));
                int plcInIo = modbusTcpNet.getByteTransform().TransUInt16(content, 14);
                int[] plcInIos = CommonUtils.byteToBits((byte) plcInIo);
                //PLC输入状态
                shuttleProtocol.setPlcInputStatus((short) plcInIos[6]);
                //当前或者之前读到的二维码值
                shuttleProtocol.setCurrentOrBeforeCode(modbusTcpNet.getByteTransform().TransInt16(content,16));
                //读到的二维码X方向偏移量
                shuttleProtocol.setCodeOffsetX(modbusTcpNet.getByteTransform().TransInt16(content,18));
                //读到的二维码Y方向偏移量
                shuttleProtocol.setCodeOffsetY(modbusTcpNet.getByteTransform().TransInt16(content,20));
                //当前的电压值
                shuttleProtocol.setCurrentVoltage(modbusTcpNet.getByteTransform().TransUInt16(content, 22));
                //当前的模拟量值
                shuttleProtocol.setCurrentAnalogValue(modbusTcpNet.getByteTransform().TransInt16(content,24));
                //当前的升降伺服速度
                shuttleProtocol.setCurrentLiftServoSpeed(modbusTcpNet.getByteTransform().TransInt16(content,26));
                //当前的行走伺服速度
                shuttleProtocol.setCurrentMoveServoSpeed(modbusTcpNet.getByteTransform().TransInt16(content,28));
                //当前的升降伺服负载率
                shuttleProtocol.setCurrentLiftServoLoad(modbusTcpNet.getByteTransform().TransInt16(content,30));
                //当前的行走伺服负载率
                shuttleProtocol.setCurrentMoveServoLoad(modbusTcpNet.getByteTransform().TransInt16(content,32));
    CommandResponse updateLocation(ShuttleCommand command);//更新坐标
                ///读取四向穿梭车状态-end
    boolean isIdle();
                //小车处于忙碌状态,将标记置为true
                if (shuttleProtocol.getBusyStatusType() == ShuttleStatusType.BUSY) {
                    shuttleProtocol.setPakMk(true);
                }
    boolean isIdle(ExecuteSupport support);//是否空闲
//                //将四向穿梭车状态保存至数据库
//                BasShuttleService shuttleService = SpringUtils.getBean(BasShuttleService.class);
//                BasShuttle basShuttle = shuttleService.selectById(slave.getId());
//                if (basShuttle == null) {
//                    basShuttle = new BasShuttle();
//                    //四向穿梭车号
//                    basShuttle.setShuttleNo(slave.getId());
//                    shuttleService.insert(basShuttle);
//                }
//                //小车忙状态位
//                basShuttle.setBusyStatus(shuttleProtocol.getBusyStatus().intValue());
//                //当前二维码
//                basShuttle.setCurrentCode(shuttleProtocol.getCurrentCode().intValue());
//                //电池电量百分比
//                basShuttle.setBatteryPower(shuttleProtocol.getBatteryPower().intValue());
//                //电池温度
//                basShuttle.setBatteryTemp(shuttleProtocol.getBatteryTemp().intValue());
//                //错误编号
//                basShuttle.setErrorCode(shuttleProtocol.getErrorCode().intValue());
//                //Plc输出状态IO
//                basShuttle.setPlcOutputStatusIo(shuttleProtocol.getPlcOutputStatusIO().intValue());
//                //错误信息码
//                basShuttle.setStatusErrorCode(shuttleProtocol.getStatusErrorCode().intValue());
//                //PLC输入状态
//                basShuttle.setPlcInputStatus(shuttleProtocol.getPlcInputStatus().intValue());
//                //当前或者之前读到的二维码值
//                basShuttle.setCurrentOrBeforeCode(shuttleProtocol.getCurrentOrBeforeCode().intValue());
//                //读到的二维码X方向偏移量
//                basShuttle.setCodeOffsetX(shuttleProtocol.getCodeOffsetX().intValue());
//                //读到的二维码Y方向偏移量
//                basShuttle.setCodeOffsetY(shuttleProtocol.getCodeOffsetY().intValue());
//                //当前的电压值
//                basShuttle.setCurrentVoltage(shuttleProtocol.getCurrentVoltage().intValue());
//                //当前的模拟量值
//                basShuttle.setCurrentAnalogValue(shuttleProtocol.getCurrentAnalogValue().intValue());
//                //当前的升降伺服速度
//                basShuttle.setCurrentLiftServoSpeed(shuttleProtocol.getCurrentLiftServoSpeed().intValue());
//                //当前的行走伺服速度
//                basShuttle.setCurrentMoveServoSpeed(shuttleProtocol.getCurrentMoveServoSpeed().intValue());
//                //当前的升降伺服负载率
//                basShuttle.setCurrentLiftServoLoad(shuttleProtocol.getCurrentLiftServoLoad().intValue());
//                //当前的行走伺服负载率
//                basShuttle.setCurrentMoveServoLoad(shuttleProtocol.getCurrentMoveServoLoad().intValue());
//                //当前小车状态(内部自我维护)
//                basShuttle.setShuttleStatus(shuttleProtocol.getProtocolStatus());
//                //任务号
//                basShuttle.setWrkNo(shuttleProtocol.getTaskNo().intValue());
//                //修改时间
//                basShuttle.setUpdateTime(new Date());
//                //作业标记
//                basShuttle.setPakMk(shuttleProtocol.getPakMk());
//                if (shuttleService.updateById(basShuttle)) {
//                    OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId()));
////                    log.info(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId()));
//                }
    boolean isDeviceIdle();//设备是否空闲
            }else {
                OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】{1}四向穿梭车plc状态信息失败", DateUtils.convert(new Date()), slave.getId()));
                throw new CoolException(MessageFormat.format( "四向穿梭车plc状态信息失败 ===>> [id:{0}] [ip:{1}] [port:{2}]", slave.getId(), slave.getIp(), slave.getPort()));
            }
        } catch (Exception e) {
            e.printStackTrace();
            OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车plc状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
            initShuttle();
        }
    }
    boolean isDeviceIdle(ExecuteSupport support);//设备是否空闲
    private boolean write(ShuttleCommand command){
        if (null == command) {
            News.error("四向穿梭车写入命令为空");
            return false;
        }
        BasShuttleService shuttleService = SpringUtils.getBean(BasShuttleService.class);
        if (shuttleService == null) {
            News.error("系统错误");
            return false;
        }
    boolean isRequireCharge();//是否满足充电状态
        BasShuttle basShuttle = shuttleService.selectById(slave.getId().shortValue());
        if (basShuttle == null) {
            News.error("四向穿梭车不存在");
            return false;
        }
        command.setShuttleNo(slave.getId().shortValue());
        short[] array = getCommandArr(command);//获取命令报文
        OperateResult result = modbusTcpNet.Write("0", array);
        if (result != null && result.IsSuccess) {
            News.info("四向穿梭车命令下发[id:{}] >>>>> {}", slave.getId(), JSON.toJSON(command));
            OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】[id:{1}] >>>>> 命令下发: {2}", DateUtils.convert(new Date()), slave.getId(), JSON.toJSON(command)));
    boolean isCharging();//是否充电中
            try {
                Thread.sleep(3000);//命令下发后休眠
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
    boolean isChargingCompleted();//是否充电完成
            for (int i = 0; i < 5; i++) {
                if (command.getCommandWord().intValue() == 5 || command.getCommandWord().intValue() == 6) {
                    break;//充电开关和系统复位不需要重发机制
                }
                readStatus();//重新读取状态
                if (shuttleProtocol.getBusyStatusType().equals(ShuttleStatusType.BUSY)) {
                    break;
                }
    List<NavigateNode> getMoveAdvancePath();//获取穿梭车任务路径
                //判断是否运行中,如不运行,重新下发命令
                result = modbusTcpNet.Write("0", array);
                News.info("四向穿梭车命令下发[id:{}] >>>>> {},次数:{}", slave.getId(), JSON.toJSON(command), i);
                OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】[id:{1}] >>>>> 命令下发: {2},次数:{}", DateUtils.convert(new Date()), slave.getId(), JSON.toJSON(command), i));
                try {
                    Thread.sleep(300);//命令下发后休眠
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
    int generateDeviceTaskNo(int taskNo, ShuttleTaskNoType type);//生成硬件设备工作号
            return true;
        } else {
            OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】写入四向穿梭车plc数据失败 ===>> [id:{1}] [ip:{2}] [port:{3}],次数:{}", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
            News.error("写入四向穿梭车plc数据失败 ===>> [id:{}] [ip:{}] [port:{}]", slave.getId(), slave.getIp(), slave.getPort());
            return false;
        }
    }
    boolean setProtocolStatus(ShuttleProtocolStatusType status);//设置工作状态
    //获取命令报文
    private short[] getCommandArr(ShuttleCommand command) {
        // 开始任务
        short[] array = new short[17];
        //控制指令字
        array[0] = command.getCommandWord();
        if (command.getStartCodeNum() != null) {
            //启始二维编号
            array[1] = command.getStartCodeNum();
        }
    boolean setTaskNo(Integer taskNo);//设置工作号
        if (command.getMiddleCodeNum() != null) {
            //中间二维编号
            array[2] = command.getMiddleCodeNum();
        }
    boolean setSyncTaskNo(Integer taskNo);//设置工作号
        if (command.getDistCodeNum() != null) {
            //目标二维编号
            array[3] = command.getDistCodeNum();
        }
    boolean setPakMk(boolean pakMk);//设置标记
        if (command.getStartToDistDistance() != null) {
            //起点到目标点的距离长度,先将int转为byte数组,再将byte数组转成两个short,分别占用4和5空间
            short[] startToDistDistances = CommonUtils.intToShorts(command.getStartToDistDistance());
            array[4] = startToDistDistances[0];
            array[5] = startToDistDistances[1];
        }
    boolean enableMoveLoc(ShuttleMoveLocParam param, boolean enable);
        if (command.getMiddleToDistDistance() != null) {
            //中间点到目标点的距离长度,先将int转为byte数组,再将byte数组转成两个short,分别占用4和5空间
            short[] middleToDistDistances = CommonUtils.intToShorts(command.getMiddleToDistDistance());
            array[6] = middleToDistDistances[0];
            array[7] = middleToDistDistances[1];
        }
    boolean requestWaiting();
        if (command.getRunDirection() != null) {
            //小车运行方向
            array[8] = command.getRunDirection();
        }
    //***************获取命令*****************
        if (command.getPalletLift() != null) {
            //托盘顶升
            array[9] = command.getPalletLift();
        }
    ShuttleCommand getMoveCommand(Integer taskNo, String startCodeNum, String distCodeNum, Integer allDistance, Integer runDirection, Integer runSpeed, List<NavigateNode> nodes);//获取移动命令
        if (command.getForceMoveDistance() != null) {
            //小车强制移动距离,先将int转为byte数组,再将byte数组转成两个short,分别占用4和5空间
            short[] forceMoveDistances = CommonUtils.intToShorts(command.getForceMoveDistance());
            array[10] = forceMoveDistances[0];
            array[11] = forceMoveDistances[1];
        }
    ShuttleCommand getLiftCommand(Integer taskNo, Boolean lift);//顶升命令 true=>顶升 false=>下降
        if (command.getChargeSwitch() != null) {
            //充电开关
            array[12] = command.getChargeSwitch();
        }
    ShuttleCommand getChargeCommand(Integer taskNo, Boolean charge);//充电开关命令 true=>开 false=>关
        if (command.getIOControl() != null) {
            //小车IO控制
            array[13] = command.getIOControl();
        }
    ShuttleCommand getUpdateLocationCommand(Integer taskNo, String locNo);//获取更新坐标命令
        if (command.getRunSpeed() != null) {
            //小车运行速度
            array[14] = command.getRunSpeed();
        }
        if (command.getRadarTmp() != null) {
            //小车雷达备用
            array[15] = command.getRadarTmp();
        }
        //指令结束位
        array[16] = command.getCommandEnd();
        return array;
    }
    /**
     * 初始化四向穿梭车
     */
    private void initShuttle() {
        this.connect();
        if (null == shuttleProtocol) {
            shuttleProtocol = new ShuttleProtocol();
        }
    }
    //分配任务
    private void assignWork(ShuttleAssignCommand assignCommand) {
//        ShuttleRedisCommand redisCommand = new ShuttleRedisCommand();
//
//        if (!assignCommand.getAuto()) {
//            List<NavigateNode> allNode = new ArrayList<>();
//            List<ShuttleCommand> commands = new ArrayList<>();
//            LocMastService locMastService = SpringUtils.getBean(LocMastService.class);
//            BasShuttleService shuttleService = SpringUtils.getBean(BasShuttleService.class);
//            NavigateMapData navigateMapData;
//
//            //获取小车移动速度
//            BasShuttle basShuttle = shuttleService.selectById(slave.getId());
//            Integer runSpeed = 1000;
////            if (basShuttle != null) {
////                Integer runSpeed1 = basShuttle.getRunSpeed();
////                if (runSpeed1 != null) {
////                    runSpeed = runSpeed1;
////                }
////            }
//
//            LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, 1);
//            LiftProtocol liftProtocol = liftThread.getLiftProtocol();
//
//            switch (assignCommand.getTaskMode()) {
//                case 1://入库
//                case 2://出库
//                    //小车移动到提升机口,计算路径
//                    //计算小车起点到中点所需命令
//                    LocMast currentLocMast = locMastService.queryByQrCode(shuttleProtocol.getCurrentCode().toString());
//                    List<NavigateNode> firstMastResult = NavigateUtils.calc(currentLocMast.getLocNo(), assignCommand.getSourceLocNo(), NavigationMapType.NORMAL.id, Utils.getShuttlePoints(assignCommand.getShuttleNo().intValue(), Utils.getLev(currentLocMast.getLocNo())));//小车到中点,处于无货状态,使用正常通道地图
//                    boolean checkResult = Utils.checkShuttlePath(firstMastResult, shuttleProtocol.getShuttleNo().intValue());
//                    if (firstMastResult != null && checkResult) {
//                        allNode.addAll(firstMastResult);//将节点进行保存
//                        //获取分段路径
//                        ArrayList<ArrayList<NavigateNode>> data = NavigateUtils.getSectionPath(firstMastResult);
//                        //将每一段路径分成command指令
//                        for (ArrayList<NavigateNode> nodes : data) {
//                            //开始路径
//                            NavigateNode startPath = nodes.get(0);
//                            //中间路径
//                            NavigateNode middlePath = nodes.get(nodes.size() - 2);
//                            //目标路径
//                            NavigateNode endPath = nodes.get(nodes.size() - 1);
//                            Integer allDistance = NavigateUtils.getCurrentPathAllDistance(nodes);//计算当前路径行走总距离
//                            Integer middleToDistDistance = NavigateUtils.getMiddleToDistDistance(nodes, middlePath);//计算中间点到目标点行走距离
//
//                            //正常移动命令
//                            Short startCode = NavigatePositionConvert.xyToPosition(startPath.getX(), startPath.getY(), startPath.getZ());//开始二维码
//                            Short middleCode = NavigatePositionConvert.xyToPosition(middlePath.getX(), middlePath.getY(), middlePath.getZ());//目标二维码
//                            Short distCode = NavigatePositionConvert.xyToPosition(endPath.getX(), endPath.getY(), endPath.getZ());//目标二维码
//                            commands.add(getMoveCommand(startCode, distCode, allDistance, ShuttleRunDirection.get(startPath.getDirection()).id, middleCode, middleToDistDistance, runSpeed));
//                        }
//
//                        //托盘顶升
//                        commands.add(getPalletCommand((short) 1));
//                    }else {
//                        //没有计算到路径,可能存在小车位置就是起点位置
//                        if (currentLocMast.getLocNo().equals(assignCommand.getSourceLocNo())) {
//                            //小车位置就是起点位置,无需移动,直接顶升
//                            //托盘顶升
//                            commands.add(getPalletCommand((short) 1));
//                        }
//                    }
//
//                    //计算中点到终点路径
//                    List<NavigateNode> secMastResult = NavigateUtils.calc(assignCommand.getSourceLocNo(), assignCommand.getLocNo(), NavigationMapType.DFX.id, Utils.getShuttlePoints(assignCommand.getShuttleNo().intValue(), Utils.getLev(assignCommand.getSourceLocNo())));//小车从中点到终点,处于有货状态,使用DFX地图
//                    boolean checkResult2 = Utils.checkShuttlePath(secMastResult, shuttleProtocol.getShuttleNo().intValue());
//                    if (secMastResult != null && checkResult2) {
//                        allNode.addAll(secMastResult);//将节点进行保存
//                        //获取分段路径
//                        ArrayList<ArrayList<NavigateNode>> data = NavigateUtils.getSectionPath(secMastResult);
//                        //将每一段路径分成command指令
//                        for (ArrayList<NavigateNode> nodes : data) {
//                            //开始路径
//                            NavigateNode startPath = nodes.get(0);
//                            //中间路径
//                            NavigateNode middlePath = nodes.get(nodes.size() - 2);
//                            //目标路径
//                            NavigateNode endPath = nodes.get(nodes.size() - 1);
//                            Integer allDistance = NavigateUtils.getCurrentPathAllDistance(nodes);//计算当前路径行走总距离
//                            Integer middleToDistDistance = NavigateUtils.getMiddleToDistDistance(nodes, middlePath);//计算中间点到目标点行走距离
//
//                            //正常移动命令
//                            Short startCode = NavigatePositionConvert.xyToPosition(startPath.getX(), startPath.getY(), startPath.getZ());//开始二维码
//                            Short middleCode = NavigatePositionConvert.xyToPosition(middlePath.getX(), middlePath.getY(), middlePath.getZ());//中间二维码
//                            Short distCode = NavigatePositionConvert.xyToPosition(endPath.getX(), endPath.getY(), endPath.getZ());//目标二维码
//                            commands.add(getMoveCommand(startCode, distCode, allDistance, ShuttleRunDirection.get(startPath.getDirection()).id, middleCode, middleToDistDistance, runSpeed));
//                        }
//
//                        //托盘下降
//                        commands.add(getPalletCommand((short) 2));
//                    }
//
//                    if (firstMastResult == null || secMastResult == null) {
//                        throw new CoolException(MessageFormat.format( "四向穿梭车出入库路径搜索失败 ===>> [id:{0}] [ip:{1}] [port:{2}]", slave.getId(), slave.getIp(), slave.getPort()));
//                    }
//
//                    navigateMapData = new NavigateMapData(Utils.getLev(currentLocMast.getLocNo()));
//                    //所使用的路径进行锁定禁用
//                    navigateMapData.writeNavigateNodeToRedisMap(firstMastResult, true);////所使用的路径进行锁定禁用
//                    navigateMapData.writeNavigateNodeToRedisMap(secMastResult, true);////所使用的路径进行锁定禁用
//                    break;
//                case 3://托盘顶升
//                case 4://托盘下降
//                    commands.add(getPalletCommand(assignCommand.getTaskMode() == 3 ? (short) 1 : (short) 2));
//                    break;
//                case 5://强制左移
//                    commands.add(getForceMoveCommand((short) 2));
//                    break;
//                case 6://强制右移
//                    commands.add(getForceMoveCommand((short) 1));
//                    break;
//                case 7://强制上移
//                    commands.add(getForceMoveCommand((short) 3));
//                    break;
//                case 8://强制下移
//                    commands.add(getForceMoveCommand((short) 4));
//                    break;
//                case 9://状态复位
//                    ShuttleCommand reset = getResetCommand();
//                    commands.add(reset);
//                    break;
//                case 10://正方向(右)寻库位
//                    commands.add(getFindLocCommand((short) 1));
//                    break;
//                case 11://负方向(左)寻库位
//                    commands.add(getFindLocCommand((short) 2));
//                    break;
//                case 12://向正方向(前)寻库位
//                    commands.add(getFindLocCommand((short) 4));
//                    break;
//                case 13://向负方向(后)寻库位
//                    commands.add(getFindLocCommand((short) 3));
//                    break;
//                case 14://移动到目标库位
//                    String startQr = shuttleProtocol.getCurrentCode().toString();//起始位置
//                    //如果穿梭车在提升机内,移动时需要先下发出提升机命令
//                    if (liftProtocol.getBarcode().intValue() == shuttleProtocol.getCurrentCode().intValue()) {
//                        //穿梭车出提升机
//                        Short liftArrival = liftProtocol.getPositionArrivalFeedback();//提升机位置反馈
//                        String liftSiteLocNo = Utils.liftArrivalToOutInStaLocNo(liftArrival);
//                        LocMast locMast1 = locMastService.selectById(liftSiteLocNo);
//                        ShuttleCommand moveCommand = getMoveCommand(liftProtocol.getBarcode(), Short.parseShort(locMast1.getQrCodeValue()), 1600, ShuttleRunDirection.BOTTOM.id, null, null, runSpeed);
//                        commands.add(moveCommand);
//
//                        //起始位置修改为提升机口站点位置
//                        startQr = locMast1.getQrCodeValue();
//                    }
//
//                    LocMast locMast = locMastService.queryByQrCode(startQr);
//                    List<NavigateNode> result = NavigateUtils.calc(locMast.getLocNo(), assignCommand.getLocNo(), NavigationMapType.NONE.id, Utils.getShuttlePoints(assignCommand.getShuttleNo().intValue(), Utils.getLev(locMast.getLocNo())));//手动命令-移动命令,使用无过滤地图
//                    boolean checkResult3 = Utils.checkShuttlePath(result, shuttleProtocol.getShuttleNo().intValue());
//                    if (result != null && checkResult3) {
//                        //所使用的路径进行锁定禁用
//                        navigateMapData = new NavigateMapData(Utils.getLev(locMast.getLocNo()));
//                        navigateMapData.writeNavigateNodeToRedisMap(result, true);////所使用的路径进行锁定禁用
//
//                        allNode.addAll(result);//将节点进行保存
//                        //获取分段路径
//                        ArrayList<ArrayList<NavigateNode>> data = NavigateUtils.getSectionPath(result);
//                        //将每一段路径分成command指令
//                        for (ArrayList<NavigateNode> nodes : data) {
//                            //开始路径
//                            NavigateNode startPath = nodes.get(0);
//                            //中间路径
//                            NavigateNode middlePath = nodes.get(nodes.size() - 2);
//                            //目标路径
//                            NavigateNode endPath = nodes.get(nodes.size() - 1);
//                            Integer allDistance = NavigateUtils.getCurrentPathAllDistance(nodes);//计算当前路径行走总距离
//                            Integer middleToDistDistance = NavigateUtils.getMiddleToDistDistance(nodes, middlePath);//计算中间点到目标点行走距离
//                            Short startCode = NavigatePositionConvert.xyToPosition(startPath.getX(), startPath.getY(), startPath.getZ());//开始二维码
//                            Short middleCode = NavigatePositionConvert.xyToPosition(middlePath.getX(), middlePath.getY(), middlePath.getZ());//中间二维码
//                            Short distCode = NavigatePositionConvert.xyToPosition(endPath.getX(), endPath.getY(), endPath.getZ());//目标二维码
//                            //正常移动命令
//                            commands.add(getMoveCommand(startCode, distCode, allDistance, ShuttleRunDirection.get(startPath.getDirection()).id, middleCode, middleToDistDistance, runSpeed));
//                        }
//                    }
//                    break;
//                case 15://充电开关
//                    commands.add(getChargeSwitchCommand());
//                    break;
//                case 16://移动到提升机
//                    LocMast locMast1 = locMastService.queryByQrCode(shuttleProtocol.getCurrentCode().toString());
//                    int lev = Utils.getLev(locMast1.getLocNo());//穿梭车当前高度
//                    String liftSiteLocNo = Utils.levToOutInStaLocNo(lev);//当前楼层站点库位号
//                    LocMast liftSitelocMast = locMastService.selectById(liftSiteLocNo);
//                    List<NavigateNode> result1 = NavigateUtils.calc(locMast1.getLocNo(), liftSiteLocNo, NavigationMapType.NONE.id, Utils.getShuttlePoints(assignCommand.getShuttleNo().intValue(), Utils.getLev(locMast1.getLocNo())));//移动到提升机,使用无过滤地图
//                    boolean checkResult4 = Utils.checkShuttlePath(result1, shuttleProtocol.getShuttleNo().intValue());
//                    Short endStartCode = null;
//                    if (result1 != null && checkResult4) {
//                        //所使用的路径进行锁定禁用
//                        navigateMapData = new NavigateMapData(Utils.getLev(locMast1.getLocNo()));
//                        navigateMapData.writeNavigateNodeToRedisMap(result1, true);////所使用的路径进行锁定禁用
//
//                        allNode.addAll(result1);//将节点进行保存
//                        //获取分段路径
//                        ArrayList<ArrayList<NavigateNode>> data = NavigateUtils.getSectionPath(result1);
//                        //将每一段路径分成command指令
//                        for (ArrayList<NavigateNode> nodes : data) {
//                            //开始路径
//                            NavigateNode startPath = nodes.get(0);
//                            //中间路径
//                            NavigateNode middlePath = nodes.get(nodes.size() - 2);
//                            //目标路径
//                            NavigateNode endPath = nodes.get(nodes.size() - 1);
//                            Integer allDistance = NavigateUtils.getCurrentPathAllDistance(nodes);//计算当前路径行走总距离
//                            Integer middleToDistDistance = NavigateUtils.getMiddleToDistDistance(nodes, middlePath);//计算中间点到目标点行走距离
//                            Short startCode = NavigatePositionConvert.xyToPosition(startPath.getX(), startPath.getY(), startPath.getZ());//开始二维码
//                            Short middleCode = NavigatePositionConvert.xyToPosition(middlePath.getX(), middlePath.getY(), middlePath.getZ());//中间二维码
//                            Short distCode = NavigatePositionConvert.xyToPosition(endPath.getX(), endPath.getY(), endPath.getZ());//目标二维码
//                            endStartCode = distCode;
//                            //正常移动命令
//                            commands.add(getMoveCommand(startCode, distCode, allDistance, ShuttleRunDirection.get(startPath.getDirection()).id, middleCode, middleToDistDistance, runSpeed));
//                        }
//                    }
//
//                    if (endStartCode == null && shuttleProtocol.getCurrentCode() == Short.parseShort(liftSitelocMast.getQrCodeValue())) {
//                        //穿梭车已经在提升机站点口
//                        endStartCode = shuttleProtocol.getCurrentCode();
//                    }
//
//                    //增加移动进提升机命令
//                    ShuttleCommand moveCommand = getMoveCommand(endStartCode, liftProtocol.getBarcode(), 1600, ShuttleRunDirection.TOP.id, null, null, runSpeed);
//                    commands.add(moveCommand);
//                    break;
//                default:
//            }
//            assignCommand.setCommands(commands);
//            assignCommand.setNodes(allNode);//当前任务所占用的节点list
//        }
//
//        redisCommand.setShuttleNo(assignCommand.getShuttleNo());//四向穿梭车号
//        redisCommand.setWrkNo(assignCommand.getTaskNo());//工作号
//        redisCommand.setCommandStep(0);//命令执行步序
//        redisCommand.setAssignCommand(assignCommand);//命令
//        shuttleProtocol.setTaskNo(assignCommand.getTaskNo());
//        shuttleProtocol.setAssignCommand(assignCommand);
//        shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.WORKING);
//        //任务数据保存到redis
//        redisUtil.set("shuttle_wrk_no_" + assignCommand.getTaskNo(), JSON.toJSONString(redisCommand));
//        //执行下发任务
//        executeWork(assignCommand.getTaskNo());
    }
    //执行下发的指令
    private boolean executeWork(Short wrkNo) {
        //读取redis数据
        if (wrkNo == null) {
            return false;
        }
//        WrkMastService wrkMastService = SpringUtils.getBean(WrkMastService.class);
//
//        Object o = redisUtil.get("shuttle_wrk_no_" + wrkNo);
//        if (o == null) {
//            return false;
//        }
//        ShuttleRedisCommand redisCommand = JSON.parseObject(o.toString(), ShuttleRedisCommand.class);
//
//        if (shuttleProtocol.getBusyStatus().intValue() == ShuttleStatusType.BUSY.id) {
//            return false;//小车状态忙
//        }
//
//        if (!checkLiftStation(wrkNo)) {//检测是否有提升机站点,有则调度提升机
//            return false;
//        }
//
//        LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, 1);
//        LiftProtocol liftProtocol = liftThread.getLiftProtocol();
//
//        List<ShuttleCommand> commands = redisCommand.getAssignCommand().getCommands();
//        //当前步序
//        int commandStep = redisCommand.getCommandStep();
//        //path路径数目
//        int size = commands.size();
//        ShuttleAssignCommand assignCommand = redisCommand.getAssignCommand();
//
//        if (commandStep != 0) {
//            //判断上一条指令是否完成
//            ShuttleCommand command = commands.get(commandStep - 1);
//            if (command.getCommandWord().intValue() == 1) {
//                //移动命令
//                if (command.getDistCodeNum().intValue() == shuttleProtocol.getCurrentCode().intValue()) {
//                    //上一条指令的目标位置和当前小车位置相同,则认定上一条任务完成
//                    command.setComplete(true);
//
//                    //上一条指令起点是提升机二维码,则清零提升机任务号
//                    if (command.getStartCodeNum().intValue() == liftProtocol.getBarcode().intValue()) {
//                        //判断提升机是否处于空闲
//                        if (liftProtocol.isIdleNoTask() && liftProtocol.getTaskNo().intValue() == redisCommand.getWrkNo().intValue()) {
//                            liftProtocol.setTaskNo((short) 0);//清空任务号
//                            WrkMast wrkMast = wrkMastService.selectById(wrkNo);
//                            if (wrkMast != null) {
//                                wrkMast.setLiftNo(null);//解锁提升机
//                                wrkMastService.updateById(wrkMast);
//                            }
//                        }
//                    }
//
//                    //入库命令,当小车取完货后,需要将提升机释放
//                    if (assignCommand.getTaskMode().intValue() == ShuttleTaskModeType.PAK_IN.id) {
//                        //判断上一条指令的起点是否为输送站点且目标点不是提升机内部二维码
//                        Short startCodeNum = command.getStartCodeNum();
//                        BasDevpService basDevpService = SpringUtils.getBean(BasDevpService.class);
//                        BasDevp basDevp = basDevpService.queryByQrCode(startCodeNum.intValue());//目标站点
//                        if (basDevp != null && command.getDistCodeNum().intValue() != liftProtocol.getBarcode().intValue()) {
//                            //上一条指令的起点为输送站点且目标点不是提升机内部二维码
//                            //此时小车应该已经离开输送站点,判断提升机是否空闲且有工作号
//                            if (liftProtocol.isIdleNoTask() && liftProtocol.getTaskNo().intValue() == redisCommand.getWrkNo().intValue()) {
//                                liftProtocol.setTaskNo((short) 0);//清空任务号
//                                WrkMast wrkMast = wrkMastService.selectById(wrkNo);
//                                if (wrkMast != null) {
//                                    wrkMast.setLiftNo(null);//解锁提升机
//                                    wrkMastService.updateById(wrkMast);
//                                }
//                            }
//                        }
//                    }
//
//                }
//            } else if (command.getCommandWord().intValue() == 2) {
//                //托盘顶升命令
//                if (command.getPalletLift().intValue() == 1) {
//                    //顶升
//                    //判断是否顶升到位
//                    if (shuttleProtocol.getPlcOutputLift()) {
//                        //自动模式
//                        if (assignCommand.getAuto() && shuttleProtocol.getPlcInputStatus().intValue() == 1) {
//                            //顶升到位,且托盘雷达有物,认定任务完成
//                            command.setComplete(true);
//                        }else {
//                            //手动模式,不判断托盘雷达
//                            //顶升到位,认定任务完成
//                            command.setComplete(true);
//                        }
//                    }
//                }else {
//                    //下降
//                    //判断是否下降到位,判断托盘雷达是否无物
//                    if (!shuttleProtocol.getPlcOutputLift() && !shuttleProtocol.getPlcOutputTransfer()) {
//                        //自动模式
//                        if (assignCommand.getAuto() && shuttleProtocol.getPlcInputStatus().intValue() == 0) {
//                            //下降到位,且托盘雷达无物,认定任务完成
//                            command.setComplete(true);
//                        }else {
//                            //手动模式,不判断托盘雷达
//                            //下降到位,且托盘雷达无物,认定任务完成
//                            command.setComplete(true);
//                        }
//                    }
//                }
//            } else if (command.getCommandWord().intValue() == 5) {
//                //充电命令
//                //判断小车充电开关
//                if (shuttleProtocol.getPlcOutputCharge()) {
//                    //正常充电,认定任务完成
//                    command.setComplete(true);
//                }
//            }
//            //任务数据保存到redis
//            redisUtil.set("shuttle_wrk_no_" + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand));
//
//            if (!command.getComplete()) {
//                //上一条任务未完成,禁止下发命令
//                return false;
//            }
//        }
//
//        if (commands.size() == 0) {
//            return false;
//        }
//
//        //取出命令
//        ShuttleCommand command = commands.get(commandStep);
//
//        if (assignCommand.getTaskMode() == ShuttleTaskModeType.PAK_IN.id.shortValue()
//            || assignCommand.getTaskMode() == ShuttleTaskModeType.PAK_OUT.id.shortValue()
//        ) {
//            //小车失去坐标,禁止下发命令
//            if (shuttleProtocol.getCurrentCode() == 0) {
//                return false;
//            }
//        }
//
//
//        //判断小车当前二维码是否为提升机二维码
//        if (shuttleProtocol.getCurrentCode().intValue() == liftProtocol.getBarcode().intValue()) {
//            //小车当前命令起始位置就是提升机二维码,说明小车需要向提升机外移动,则需要判断状态是否满足
//            if (command.getStartCodeNum().intValue() == liftProtocol.getBarcode().intValue()){
//                //提升机是否空闲,提升机是否到达目标楼层,目标楼层是否给出提升机到位信号位
//                if (!liftProtocol.isIdleNoTask()) {
//                    return false;//提升机忙,禁止下发命令
//                }
//                if (liftProtocol.getTaskNo().intValue() != 0 && liftProtocol.getTaskNo().intValue() != wrkNo) {
//                    //提升机工作号和当前工作不相同,禁止下发命令
//                    return false;
//                }
//
//                Short distCodeNum = command.getDistCodeNum();//目标二维码
//                BasDevpService basDevpService = SpringUtils.getBean(BasDevpService.class);
//                BasDevp basDevp = basDevpService.queryByQrCode(distCodeNum.intValue());//目标站点
//                if (basDevp == null) {
//                    return false;//找不到目标站,禁止下发命令
//                }
//
//                int lev = Utils.getLev(basDevp.getLocNo());//目标二维码所在楼层
//                int liftLev = liftProtocol.getLev().intValue();//提升机所在楼层
//                if (liftLev != lev) {
//                    return false;//提升机不在目标楼层,禁止下发命令
//                }
//
//                //获取目标站信息
//                SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, 1);
//                StaProtocol staProtocol = devpThread.getStation().get(basDevp.getDevNo());
//                if (staProtocol == null) {
//                    return false;//站点信息不存在,禁止下发命令
//                }
//                if (!staProtocol.isLiftArrival()) {
//                    return false;//站点提升机到位信号false,禁止下发命令
//                }
//
//                //条件满足,占用提升机
//                liftProtocol.setTaskNo(wrkNo);
//            }
//        }
//
//        //下发命令
//        if (!write(command)) {
//            News.error("四向穿梭车命令下发失败,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
//            return false;
//        } else {
//            News.info("四向穿梭车命令下发成功,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
//
//            //将标记置为false(防止重发)
//            shuttleProtocol.setPakMk(false);
//
//            //保存数据到数据库做流水
//            BasShuttleOptService shuttleOptService = SpringUtils.getBean(BasShuttleOptService.class);
//            if (shuttleOptService != null) {
//                short[] commandArr = getCommandArr(command);//获取命令报文
//                BasShuttleOpt opt = new BasShuttleOpt(
//                        assignCommand.getTaskNo().intValue(),
//                        assignCommand.getShuttleNo().intValue(),
//                        new Date(),
//                        ShuttleTaskModeType.get(assignCommand.getTaskMode()).desc,
//                        assignCommand.getSourceLocNo(),
//                        assignCommand.getLocNo(),
//                        null,
//                        null,
//                        null,
//                        JSON.toJSONString(command),
//                        JSON.toJSONString(commandArr)
//                );
//                shuttleOptService.insert(opt);
//            }
//
//            //判断数据是否执行完成
//            if (commandStep < size - 1) {
//                //更新redis数据
//                //步序增加
//                commandStep++;
//                redisCommand.setCommandStep(commandStep);
//                //任务数据保存到redis
//                redisUtil.set("shuttle_wrk_no_" + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand));
//            }else {
//                //已执行完成
//
//                if (redisCommand.getLiftSecurityMk()) {
//                    //曾锁定过提升机,需要进行解锁
//                    if (liftProtocol != null) {
//                        liftProtocol.setSecurityMk(false);
//                    }
//                }
//
//                String locNo = shuttleProtocol.getLocNo() == null ? shuttleProtocol.getSourceLocNo() : shuttleProtocol.getLocNo();
//                if (locNo != null) {
//                    //解除锁定的库位路径
//                    NavigateMapData navigateMapData = new NavigateMapData(Utils.getLev(locNo));
//                    navigateMapData.writeNavigateNodeToRedisMap(redisCommand.getAssignCommand().getNodes(), false);
//                }
//
//                //删除redis
//                redisUtil.del("shuttle_wrk_no_" + redisCommand.getWrkNo());
//
//                if (!assignCommand.getAuto()) {
//                    //手动模式不抛出等待状态,直接复位
//                    //设置四向穿梭车为空闲状态
//                    shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.IDLE);
//                    //任务号清零
//                    shuttleProtocol.setTaskNo((short) 0);
//                    //标记复位
//                    shuttleProtocol.setPakMk(true);
//                    News.info("四向穿梭车手动任务执行完成,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
//                }else {
//                    if (!assignCommand.getCharge()) {
//                        //对主线程抛出等待确认状态waiting
//                        shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.WAITING);
//                    }else {
//                        shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.CHARGING_WAITING);
//                    }
//                    News.info("四向穿梭车任务执行下发完成等待执行结束,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
//                }
//
//            }
//
//        }
        return true;
    }
    /**
     * 检测是否有提升机站点,有则调度提升机
     */
    private boolean checkLiftStation(Short wrkNo) {
        //读取redis数据
        if (wrkNo == null) {
            return false;
        }
//        //拿到提升机线程
//        LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, 1);
//        if (liftThread == null) {
//            return false;
//        }
//        LiftProtocol liftProtocol = liftThread.getLiftProtocol();
//        if (liftProtocol == null) {
//            return false;
//        }
//
//        Object o = redisUtil.get("shuttle_wrk_no_" + wrkNo);
//        if (o == null) {
//            return false;
//        }
//        ShuttleRedisCommand redisCommand = JSON.parseObject(o.toString(), ShuttleRedisCommand.class);
//        //当前步序
//        int commandStep = redisCommand.getCommandStep();
//
//        //检测是否存在提升机口的指令
//        List<ShuttleCommand> commands = redisCommand.getAssignCommand().getCommands();
//        if (commands.size() > 0) {
//            if (commands.get(commandStep).getCommandWord() != 1) {
//                //不是行走命令,直接放行
//                return true;
//            }
//
//            if (commands.get(0).getStartCodeNum() == null) {
//                return false;
//            }
//        }
//
//        if (commands.size() == 0) {
//            return false;
//        }
//
//        //当前等待执行的指令
//        ShuttleCommand command = commands.get(commandStep);
//
//        BasDevpService basDevpService = SpringUtils.getBean(BasDevpService.class);
//        ArrayList<Short> qrCodeValues = new ArrayList<>();
//        for (BasDevp basDevp : basDevpService.selectList(null)) {
//            //将所有提升机口二维码存入list
//            qrCodeValues.add(Short.parseShort(basDevp.getQrCodeValue()));
//        }
//
//        Integer siteNo = null;//站点号
//        for (Short qrCodeValue : qrCodeValues) {
//            //目标位置是提升机口,或起点位置是提升机口且目标是去提升机内
//            if (command.getDistCodeNum() == null || command.getStartCodeNum() == null) {
//                continue;
//            }
//
//            if (qrCodeValue.intValue() == command.getDistCodeNum().intValue() || (qrCodeValue.intValue() == command.getStartCodeNum().intValue() && command.getDistCodeNum().intValue() == liftProtocol.getBarcode().intValue())) {
//                //存在
//                BasDevp basDevp = basDevpService.queryByQrCode(qrCodeValue.intValue());
//                siteNo = basDevp.getDevNo();
//                break;
//            }
//        }
//
//        if (siteNo == null) {
//            //找不到站点,说明还未到提升机
//            return true;
//        }
//
//
////        //遍历所有指令,判断是否有到提升机口的指令或从提升机口前往提升机内的指令,并获取到达该提升机口所需步序
////        int step = 0;
////        Integer siteNo = null;//站点号
////        ShuttleCommand command = null;
////        for (int i = 0; i < commands.size(); i++) {
////            command = commands.get(i);
////            for (Short qrCodeValue : qrCodeValues) {
////                //目标位置是提升机口,或起点位置是提升机口且目标是去提升机内
////                if (command.getDistCodeNum() == null || command.getStartCodeNum() == null) {
////                    continue;
////                }
////
////                if (qrCodeValue.intValue() == command.getDistCodeNum().intValue() || (qrCodeValue.intValue() == command.getStartCodeNum().intValue() && command.getDistCodeNum().intValue() == liftProtocol.getBarcode().intValue())) {
////                    //存在
////                    step = i + 1;
////                    BasDevp basDevp = basDevpService.queryByQrCode(qrCodeValue.intValue());
////                    siteNo = basDevp.getDevNo();
////                    break;
////                }
////            }
////        }
////
////        if (step == 0) {
////            //无需后续检测,直接放行
////            return true;
////        }
//
//        //判断下一步是否为提升机口或提升机内
//        if (commandStep < commands.size()) {
//            ShuttleCommand command1 = commands.get(commandStep);
//            Short distCodeNum = command1.getDistCodeNum();
//            if (distCodeNum != null) {
//                BasDevp basDevp = basDevpService.queryByQrCode(Integer.valueOf(distCodeNum));
//                if (basDevp == null && distCodeNum.intValue() != liftProtocol.getBarcode().intValue()) {
//                    return true;//下一步不是提升机口,跳过后续流程
//                }
//            }
//        }
//
//        //获取四向穿梭车当前楼层
//        String shuttleLocNo = shuttleProtocol.getCurrentLocNo();//二维码对应库位号
//        Integer shuttleLocNoLev = shuttleLocNo == null ? 0 : Utils.getLev(shuttleLocNo);//库位号对应层高
//
//        //判断穿梭车和提升机是否在目标楼层
//        if (shuttleLocNoLev >= 2) {
//            shuttleLocNoLev++;
//        }
//
//        //判断输送线站点是否给出提升机到位信号
//        SiemensDevpThread siemensDevpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, 1);
//        StaProtocol staProtocol = siemensDevpThread.getStation().get(siteNo);
//        if (!staProtocol.isLiftArrival()) {
//            //输送线反馈提升机没有到位
//            executeLift(liftThread, liftProtocol, redisCommand, shuttleLocNoLev);//调度提升机
//            return false;
//        }
//
//        if (shuttleProtocol.getCurrentCode().intValue() == liftProtocol.getBarcode().intValue()) {
//            //小车处于提升机内
//            return true;
//        }else {
//            if (liftProtocol.getPositionArrivalFeedback$() == shuttleLocNoLev) {
//                //判断提升机是否有任务号
//                if (liftProtocol.getTaskNo().intValue() != 0) {
//                    //判断任务号是否和当前小车任务一致
//                    if (liftProtocol.getTaskNo().intValue() != wrkNo.intValue()) {
//                        return false;//任务号不一致,且提升机任务号不为0
//                    }
//                }
//                liftProtocol.setTaskNo(wrkNo);//给提升机写工作号,防止被占用
//                WrkMastService wrkMastService = SpringUtils.getBean(WrkMastService.class);
//                WrkMast wrkMast = wrkMastService.selectById(shuttleProtocol.getTaskNo());
//                if (wrkMast != null) {
//                    wrkMast.setLiftNo(liftProtocol.getLiftNo().intValue());//锁定提升机,防止被抢占
//                    wrkMastService.updateById(wrkMast);
//                }
//                return true;//提升机到位
//            }
//            executeLift(liftThread, liftProtocol, redisCommand, shuttleLocNoLev);//调度提升机
//            return false;//提升机没有到位
//        }
        return false;
    }
    private boolean executeLift(LiftThread liftThread, LiftProtocol liftProtocol, ShuttleRedisCommand redisCommand, Integer shuttleLocNoLev) {//调度提升机
        if (!liftProtocol.isIdle()) {
            //提升机不空闲禁止下发
            return false;
        }
//        if (liftProtocol.getPlatShuttleCheck()) {
//            //提升机内有车禁止下发
//            return false;
//        }
        if (redisCommand.getLiftSecurityMk()) {
            //已经执行过提升机命令,禁止下发
            return false;
        }
        WrkMastService wrkMastService = SpringUtils.getBean(WrkMastService.class);
        WrkMast wrkMast = wrkMastService.selectById(shuttleProtocol.getTaskNo());
        if (wrkMast != null) {
            wrkMast.setLiftNo(liftProtocol.getLiftNo().intValue());//锁定提升机,防止被抢占
            wrkMastService.updateById(wrkMast);
        }
        //给提升机分配任务
        liftProtocol.setTaskNo(shuttleProtocol.getTaskNo());//设置任务号
        liftProtocol.setShuttleNo(shuttleProtocol.getShuttleNo());//设置四向穿梭车号
        liftProtocol.setProtocolStatus(LiftProtocolStatusType.WORKING);//设置提升机状态为工作中
//        liftProtocol.setSecurityMk(true);//标记置为true,防止其他任务占用当前提升机
        redisCommand.setLiftSecurityMk(true);//标记置为true,防止其他任务占用当前提升机
        //任务数据保存到redis
        redisUtil.set("shuttle_wrk_no_" + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand));
        //命令list
        ArrayList<LiftCommand> liftCommands = new ArrayList<>();
//        LiftCommand liftCommand = liftThread.getLiftUpDownCommand(liftProtocol.getLiftNo(), liftProtocol.getTaskNo(), shuttleLocNoLev);
//        liftCommands.add(liftCommand);//将命令添加进list
        LiftAssignCommand liftAssignCommand = new LiftAssignCommand();
//        liftAssignCommand.setCommands(liftCommands);
        liftAssignCommand.setLiftNo(liftProtocol.getLiftNo());
        liftAssignCommand.setTaskNo(liftProtocol.getTaskNo());
        //下发任务
        MessageQueue.offer(SlaveType.Lift, liftProtocol.getLiftNo().intValue(), new Task(3, liftAssignCommand));
        return true;
    }
    /**
     * 获取托盘顶升命令
     * @param lift 1顶升,2下降
     */
    public ShuttleCommand getPalletCommand(Short lift) {
        ShuttleCommand command = new ShuttleCommand();
        command.setCommandWord((short) 2);
        command.setStartCodeNum((short) 0);
        command.setMiddleCodeNum((short) 0);
        command.setDistCodeNum((short) 0);
        command.setStartToDistDistance(0);
        command.setMiddleToDistDistance(0);
        command.setRunDirection((short) 0);
        command.setForceMoveDistance(0);
        command.setPalletLift(lift);
        command.setRunSpeed((short) 0);
        command.setCommandEnd((short) 1);
        return command;
    }
    /**
     * 正常移动命令,默认移动速度1000
     */
    public ShuttleCommand getMoveCommand(Short startCodeNum, Short distCodeNum, Integer startToDistDistance, Short runDirection, Short middleCodeNum, Integer middleToDistDistance) {
        return getMoveCommand(startCodeNum, distCodeNum, startToDistDistance, runDirection, middleCodeNum, middleToDistDistance, 500);
    }
    /**
     * 正常移动命令
     */
    public ShuttleCommand getMoveCommand(Short startCodeNum, Short distCodeNum, Integer startToDistDistance, Short runDirection, Short middleCodeNum, Integer middleToDistDistance, Integer runSpeed) {
        ShuttleCommand command = new ShuttleCommand();
        command.setCommandWord((short) 1);
        command.setStartCodeNum(startCodeNum);
        command.setMiddleCodeNum(middleCodeNum);
        command.setDistCodeNum(distCodeNum);
        command.setStartToDistDistance(startToDistDistance);
        command.setMiddleToDistDistance(middleToDistDistance);
        command.setRunDirection(runDirection);
        command.setForceMoveDistance(0);
        command.setIOControl((short) 0);
        command.setRunSpeed(runSpeed.shortValue());
        command.setCommandEnd((short) 1);
        return command;
    }
    /**
     * 强制移动命令
     * @param direction 移动方向 1左移,2右移,3前移,4后移
     */
    public ShuttleCommand getForceMoveCommand(Short direction) {
        ShuttleCommand command = new ShuttleCommand();
        command.setCommandWord((short) 3);
        command.setStartCodeNum((short) 0);
        command.setMiddleCodeNum((short) 0);
        command.setDistCodeNum((short) 0);
        command.setStartToDistDistance(600);
        command.setRunDirection(direction);
        command.setForceMoveDistance(600);
        command.setIOControl((short) 0);
        command.setCommandEnd((short) 1);
        command.setRunSpeed((short) 1000);
        return command;
    }
    /**
     * 状态复位命令
     */
    public ShuttleCommand getResetCommand() {
        ShuttleCommand command = new ShuttleCommand();
        command.setCommandWord((short) 6);
        command.setStartCodeNum((short) 0);
        command.setMiddleCodeNum((short) 0);
        command.setDistCodeNum((short) 0);
        command.setStartToDistDistance(0);
        command.setMiddleToDistDistance(0);
        command.setRunDirection((short) 0);
        command.setPalletLift((short) 0);
        command.setPalletLift((short) 0);
        command.setForceMoveDistance(0);
        command.setChargeSwitch((short) 0);
        command.setIOControl((short) 0);
        command.setRunSpeed((short) 0);
        command.setCommandEnd((short) 1);
        return command;
    }
    /**
     * 获取寻库位命令
     * @param direction 1:向正方向(左)寻库位,2:向负方向(右)寻库位,3:向负方向(后)寻库位,4:向正方向(前)寻库位
     */
    public ShuttleCommand getFindLocCommand(Short direction, Integer startToDistance, Short runSpeed) {
        ShuttleCommand command = new ShuttleCommand();
        command.setCommandWord((short) 4);
        command.setRunDirection(direction);
        command.setStartToDistDistance(startToDistance);
        command.setRunSpeed((short) runSpeed);
        command.setCommandEnd((short) 1);
        return command;
    }
    /**
     * 获取寻库位命令,默认移动距离3000,运行速度1000
     * @param direction 1:向正方向(左)寻库位,2:向负方向(右)寻库位,3:向负方向(后)寻库位,4:向正方向(前)寻库位
     */
    public ShuttleCommand getFindLocCommand(Short direction) {
        return getFindLocCommand(direction, 3000, (short) 1000);
    }
    /**
     * 获取充电开关命令
     */
    public ShuttleCommand getChargeSwitchCommand() {
        ShuttleCommand command = new ShuttleCommand();
        command.setCommandWord((short) 5);
        command.setChargeSwitch((short) 1);
        command.setCommandEnd((short) 1);
        return command;
    }
    /**
     * charge:1=>开始充电,2=>断开充电
     */
    public ShuttleCommand getChargeSwitchCommand(Short charge) {
        ShuttleCommand command = new ShuttleCommand();
        command.setCommandWord((short) 5);//充电
        command.setShuttleNo(shuttleProtocol.getShuttleNo());
        command.setChargeSwitch(charge);//开始充电
        command.setCommandEnd((short) 1);
        return command;
    }
    /******************************************************************************************/
    /**************************************** 测试专用 *****************************************/
    /*****************************************************************************************/
    public static void main(String[] args) throws InterruptedException {
        ShuttleSlave slave = new ShuttleSlave();
        slave.setId(1);
        slave.setIp("192.168.4.24");
        slave.setPort(502);
//        ShuttleThread thread = new ShuttleThread(slave);
//        thread.connect();
//        thread.readStatus();
//
//        ShuttleCommand command = new ShuttleCommand();
//        command.setCommandWord((short) 0);
//        command.setStartCodeNum((short) 12323);
//        command.setMiddleCodeNum((short) 22323);
//        command.setDistCodeNum((short) 29999);
//        command.setStartToDistDistance(109999);
//        command.setMiddleToDistDistance(5000);
//        command.setRunDirection((short) 1);
//        command.setPalletLift((short) 2);
//        command.setForceMoveDistance(3000);
//        command.setChargeSwitch((short) 2);
//        command.setIOControl((short) 0);
//        command.setRunSpeed((short) 0);
//        command.setRadarTmp((short) 0);
//        command.setCommandEnd((short) 1);
//        thread.write(command);
    }
}
src/main/java/com/zy/core/thread/SiemensCrnThread.java
File was deleted
src/main/java/com/zy/core/thread/SteThread.java
File was deleted
src/main/java/com/zy/core/thread/impl/NyShuttleThread.java
New file
@@ -0,0 +1,1150 @@
package com.zy.core.thread.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.DateUtils;
import com.core.common.SpringUtils;
import com.core.exception.CoolException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zy.asrs.entity.BasShuttle;
import com.zy.asrs.entity.DeviceDataLog;
import com.zy.asrs.entity.LocMast;
import com.zy.asrs.service.BasShuttleService;
import com.zy.asrs.service.DeviceDataLogService;
import com.zy.asrs.service.LocMastService;
import com.zy.asrs.utils.Utils;
import com.zy.common.ExecuteSupport;
import com.zy.common.model.MapNode;
import com.zy.common.model.NavigateNode;
import com.zy.common.model.enums.NavigationMapType;
import com.zy.common.utils.NavigateMapData;
import com.zy.common.utils.NavigatePositionConvert;
import com.zy.common.utils.RedisUtil;
import com.zy.core.News;
import com.zy.core.action.ShuttleAction;
import com.zy.core.cache.OutputQueue;
import com.zy.core.enums.*;
import com.zy.core.model.CommandResponse;
import com.zy.core.model.ShuttleSlave;
import com.zy.core.model.command.NyShuttleHttpCommand;
import com.zy.core.model.command.ShuttleCommand;
import com.zy.core.model.command.ShuttleRedisCommand;
import com.zy.core.model.param.ShuttleMoveLocParam;
import com.zy.core.model.protocol.ShuttleProtocol;
import com.zy.core.thread.ShuttleThread;
import com.zy.system.entity.Config;
import com.zy.system.service.ConfigService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.text.MessageFormat;
import java.util.*;
@Slf4j
@SuppressWarnings("all")
public class NyShuttleThread implements ShuttleThread {
    private ShuttleSlave slave;
    private RedisUtil redisUtil;
    private ShuttleProtocol shuttleProtocol;
    private Socket socket;
    private static final boolean DEBUG = false;//调试模式
    private List<JSONObject> socketResults = new ArrayList<>();
    //原始设备数据
    private Object originDeviceData;
    public NyShuttleThread(ShuttleSlave slave, RedisUtil redisUtil) {
        this.slave = slave;
        this.redisUtil = redisUtil;
    }
    @Override
    public void run() {
        News.info("{}号四向车线程启动", slave.getId());
        this.connect();
        //监听消息并存储
        Thread innerThread = new Thread(() -> {
            while (true) {
                try {
                    listenSocketMessage();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        innerThread.start();
        //设备读取
        Thread readThread = new Thread(() -> {
            while (true) {
                try {
                    read();
                    Thread.sleep(50);
                } catch (Exception e) {
                    log.error("ShuttleThread Fail", e);
                }
            }
        });
        readThread.start();
        //设备执行
        Thread executeThread = new Thread(() -> {
            while (true) {
                try {
                    ShuttleAction shuttleAction = SpringUtils.getBean(ShuttleAction.class);
                    if (shuttleAction == null) {
                        continue;
                    }
                    Object object = redisUtil.get(RedisKeyType.SHUTTLE.key + slave.getId());
                    if (object == null) {
                        continue;
                    }
                    Integer taskNo = Integer.valueOf(String.valueOf(object));
                    if (taskNo != 0) {
                        //存在任务需要执行
                        boolean result = shuttleAction.executeWork(slave.getId(), taskNo);
                    }
//                    //小车空闲且有跑库程序
//                    shuttleAction.moveLoc(slave.getId());
                    Thread.sleep(200);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        executeThread.start();
        //其他任务
        Thread otherThread = new Thread(() -> {
            while (true) {
                try {
                    listenInit();//监听初始化事件
                    saveLog();//保存数据
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        otherThread.start();
    }
    private void saveLog() {
        if (shuttleProtocol == null) {
            return;
        }
        if (System.currentTimeMillis() - shuttleProtocol.getDeviceDataLog() > 1000 * 5) {
            if (this.originDeviceData != null) {
                //采集时间超过5s,保存一次数据记录
                //保存数据记录
                DeviceDataLogService deviceDataLogService = SpringUtils.getBean(DeviceDataLogService.class);
                DeviceDataLog deviceDataLog = new DeviceDataLog();
                deviceDataLog.setOriginData(JSON.toJSONString(this.originDeviceData));
                deviceDataLog.setWcsData(JSON.toJSONString(shuttleProtocol));
                deviceDataLog.setType(String.valueOf(SlaveType.Shuttle));
                deviceDataLog.setDeviceNo(slave.getId());
                deviceDataLog.setCreateTime(new Date());
                deviceDataLogService.insert(deviceDataLog);
                //更新采集时间
                shuttleProtocol.setDeviceDataLog(System.currentTimeMillis());
            }
        }
        //将四向穿梭车状态保存至数据库
        BasShuttleService shuttleService = SpringUtils.getBean(BasShuttleService.class);
        BasShuttle basShuttle = shuttleService.selectOne(new EntityWrapper<BasShuttle>()
                .eq("shuttle_no", slave.getId()));
        if (basShuttle == null) {
            basShuttle = new BasShuttle();
            //四向穿梭车号
            basShuttle.setShuttleNo(slave.getId());
            basShuttle.setStatus(1);
            shuttleService.insert(basShuttle);
        }
        //任务号
        basShuttle.setWrkNo(shuttleProtocol.getTaskNo().intValue());
        //修改时间
        basShuttle.setUpdateTime(new Date());
        //设备状态
        basShuttle.setDeviceStatus(JSON.toJSONString(shuttleProtocol));
        if (shuttleService.updateById(basShuttle)) {
            OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId()));
        }
    }
    private void listenSocketMessage() {
        try {
            if (this.socket == null) {
                return;
            }
            // 获取输入流
            BufferedReader reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
            // 读取服务器的响应
            StringBuffer sb = new StringBuffer();
            char[] chars = new char[2048];//缓冲区
            while (true) {
                reader.read(chars);
                String trim = new String(chars);
                sb.append(trim);
                if (trim.lastIndexOf("\r\n") != -1) {
                    break;
                }
            }
            JSONObject result = JSON.parseObject(sb.toString());//得到响应结果集
            if (!socketResults.isEmpty() && socketResults.size() >= 5) {
                socketResults.remove(0);//清理头节点
            }
            socketResults.add(result);//添加数据
        } catch (Exception e) {
//            e.printStackTrace();
        }
    }
    public JSONObject getRequestBody(String type) {
        try {
            // 获取服务器响应
            JSONObject result = null;
            if (type.equals("readState")) {
                type = "state";
            }
            for (int i = 0; i < socketResults.size(); i++) {
                JSONObject socketResult = socketResults.get(i);
                if (!socketResult.get("msgType").equals("responseMsg")) {//不是响应内容
                    continue;
                }
                JSONObject resultResponse = JSON.parseObject(socketResult.get("response").toString());
                JSONObject resultBody = JSON.parseObject(resultResponse.get("body").toString());
                String responseType = resultBody.get("responseType").toString();
                if (DEBUG) {
                    result = socketResult;
                    break;
                }
                if (!responseType.equals(type)) {
                    continue;//响应ID与请求ID不一致,不在调试模式下
                }
                result = socketResult;
                break;
            }
            if (result == null) {
                return null;//无响应结果
            }
            return filterBodyData(result);//返回Body结果集
        } catch (Exception e) {
            return null;
        }
    }
    private void read() {
        try {
            if (this.socket == null || this.socket.isClosed()) {
                //链接断开重新链接
                this.connect();
            }
            readStatus();
        } catch (Exception e) {
            e.printStackTrace();
            OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】读取四向穿梭车状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
        }
    }
    private void readStatus() {
        try {
            if (null == shuttleProtocol) {
                shuttleProtocol = new ShuttleProtocol();
                shuttleProtocol.setShuttleNo(slave.getId());
                shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.IDLE);
                InnerSuhttleExtend extend = new InnerSuhttleExtend();
                shuttleProtocol.setExtend(extend);
            }
            //----------读取四向穿梭车状态-----------
            NyShuttleHttpCommand readStatusCommand = getReadStatusCommand(slave.getId());
            JSONObject data = requestCommand(readStatusCommand);
            if (data == null) {
                if (System.currentTimeMillis() - shuttleProtocol.getLastOnlineTime() > 1000 * 60) {
                    //最后一次上线时间超过60s,认定离线
                    shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.OFFLINE);
                }
                OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车Socket状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
            }else {
                //----------读取四向穿梭车状态-----------
                //小车设备状态
                shuttleProtocol.setDeviceStatus(data.getInteger("free"));
                //小车模式
                shuttleProtocol.setMode(data.getInteger("workingMode"));
                //当前二维码
                shuttleProtocol.setCurrentCode(data.getString("point"));
                //电池电量
                shuttleProtocol.setBatteryPower(data.getString("powerPercent"));
                //电池电压
                shuttleProtocol.setBatteryVoltage(data.getInteger("voltage"));
                //故障
                shuttleProtocol.setErrorCode(data.getJSONArray("errCode").getString(0));
                //是否顶升
                shuttleProtocol.setHasLift(data.getInteger("liftPosition") == 2 ? true : false);
                //是否有托盘
                shuttleProtocol.setHasPallet(data.getInteger("loadState") == 1 ? true : false);
                //行驶方向
                shuttleProtocol.setRunDirection(data.getString("runDir") == null ? "none" : data.getString("runDir"));
                //是否为充电状态
                shuttleProtocol.setHasCharge(data.getInteger("chargState") == 1 ? true : false);
                //*********读取扩展字段**********
                InnerSuhttleExtend extend = (InnerSuhttleExtend) shuttleProtocol.getExtend();
                //管制状态
                extend.setSuspendState(data.getInteger("suspendState"));
                //当前速度
                extend.setSpeed(data.getInteger("speed"));
                //剩余电量
                extend.setSurplusQuantity(data.getInteger("surplusQuantity"));
                //总电量
                extend.setCountQuantity(data.getInteger("countQuantity"));
                shuttleProtocol.setExtend(extend);//扩展字段
                //最近一次在线时间
                shuttleProtocol.setLastOnlineTime(System.currentTimeMillis());
                ///读取四向穿梭车状态-end
                //小车处于运行中,将标记置为true
                if (shuttleProtocol.getDeviceStatus() == 1) {
                    shuttleProtocol.setPakMk(true);
                }
                if (shuttleProtocol.getProtocolStatusType() == null && shuttleProtocol.getDeviceStatus().intValue() == 0) {
                    //小车空闲状态、小车任务状态为未知,认定曾离线过,需要复位成空闲
                    shuttleProtocol.setProtocolStatusType(ShuttleProtocolStatusType.IDLE);
                }
                this.originDeviceData = data;
                OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId()));
            }
        } catch (Exception e) {
            e.printStackTrace();
            OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车Socket状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
            try {
                this.socket.close();
                this.socket = null;
                Thread.sleep(1000);
                this.connect();
            } catch (IOException | InterruptedException exception) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 监听小车复位初始化信号
     */
    public void listenInit() {
        try {
            // 获取服务器响应
            JSONObject result = null;
            int removeIdx = -1;
            for (int i = 0; i < socketResults.size(); i++) {
                JSONObject socketResult = socketResults.get(i);
                if (!socketResult.get("msgType").equals("requestMsg")) {//不是请求内容
                    continue;
                }
                JSONObject resultResponse = JSON.parseObject(socketResult.get("request").toString());
                JSONObject resultHeader = JSON.parseObject(resultResponse.get("header").toString());
                JSONObject resultBody = JSON.parseObject(resultResponse.get("body").toString());
                String requestType = resultBody.getString("requestType");
                Integer requestId = resultHeader.getInteger("requestId");
                if (requestType.equals("init")) {
                    Integer code = resultBody.getInteger("code");
                    //小车复位请求
                    ShuttleCommand initCommand = getInitCommand(requestId, code);
                    //发出请求
                    NyShuttleHttpCommand httpCommand = JSON.parseObject(initCommand.getBody(), NyShuttleHttpCommand.class);
                    JSONObject requestResult = requestCommand(httpCommand);
                    removeIdx = i;//此数据已经处理,从结果集中剔除
                    log.info(MessageFormat.format("【{0}】四向车复位上报 ===>> [code:{1}] [ip:{2}] [port:{3}]", slave.getId(), code, slave.getIp(), slave.getPort()));
                    OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向车复位上报 ===>> [code:{1}] [ip:{2}] [port:{3}]", slave.getId(), code, slave.getIp(), slave.getPort()));
                    break;
                }
            }
            if (removeIdx != -1) {
                socketResults.remove(removeIdx);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @Override
    public ShuttleProtocol getStatus() {
        return getStatus(true);
    }
    @Override
    public ShuttleProtocol getStatus(boolean clone) {
        if (this.shuttleProtocol == null) {
            return null;
        }
        return clone ? this.shuttleProtocol.clone() : this.shuttleProtocol;
    }
    @Override
    public CommandResponse movePath(List<NavigateNode> nodes, Integer taskNo) {
        CommandResponse response = new CommandResponse(true);
        return response;
    }
    @Override
    public CommandResponse move(ShuttleCommand command) {
        CommandResponse response = new CommandResponse(false);
        try {
            //发出请求
            NyShuttleHttpCommand httpCommand = JSON.parseObject(command.getBody(), NyShuttleHttpCommand.class);
            Map<String, Object> body = httpCommand.getRequest().getBody();
            Object pathObj = body.get("path");
            int taskId = Integer.parseInt(body.get("taskId").toString());
            List<JSONObject> path = JSON.parseArray(JSON.toJSONString(pathObj), JSONObject.class);
            ArrayList<NyShuttleHttpCommand> commandList = new ArrayList<>();
            while (!path.isEmpty()) {
                ArrayList<Map<String, Object>> list = new ArrayList<>();
                if (path.size() > 10) {
                    List<JSONObject> subList = path.subList(0, 10);
                    list.addAll(subList);
                    List<JSONObject> tmp = new ArrayList<>();
                    for (int i = 10; i < path.size(); i++) {
                        tmp.add(path.get(i));
                    }
                    path = tmp;
                }else  {
                    list.addAll(path);
                    path.clear();
                }
                NyShuttleHttpCommand httpCommandCopy = JSON.parseObject(JSON.toJSONString(httpCommand), NyShuttleHttpCommand.class);
                JSONObject bodyCopy = JSON.parseObject(JSON.toJSONString(body));
                NyShuttleHttpCommand.NyRequest request = httpCommandCopy.getRequest();
                bodyCopy.put("path", list);
                bodyCopy.put("taskId", taskId++);
                request.setBody(bodyCopy);
                httpCommandCopy.setRequest(request);
                commandList.add(httpCommandCopy);//add copy
            }
            for (NyShuttleHttpCommand requestCommand : commandList) {
                JSONObject result = requestCommand(requestCommand);
                if (result == null) {
                    return response;//请求失败
                }
                this.shuttleProtocol.setSendTime(System.currentTimeMillis());//指令下发时间
                response.setMessage(JSON.toJSONString(result));
                response.setResult(true);
            }
            return response;
        } catch (Exception e) {
            e.printStackTrace();
            response.setMessage(e.getMessage());
            return response;
        }
    }
    @Override
    public CommandResponse lift(ShuttleCommand command) {
        CommandResponse response = new CommandResponse(false);
        try {
            //发出请求
            NyShuttleHttpCommand httpCommand = JSON.parseObject(command.getBody(), NyShuttleHttpCommand.class);
            JSONObject result = requestCommand(httpCommand);
            if (result == null) {
                return response;//请求失败
            }
            this.shuttleProtocol.setSendTime(System.currentTimeMillis());//指令下发时间
            response.setMessage(JSON.toJSONString(result));
            response.setResult(true);
            return response;
        } catch (Exception e) {
            e.printStackTrace();
            return response;
        }
    }
    @Override
    public CommandResponse charge(ShuttleCommand command) {
        CommandResponse response = new CommandResponse(false);
        try {
            //发出请求
            NyShuttleHttpCommand httpCommand = JSON.parseObject(command.getBody(), NyShuttleHttpCommand.class);
            JSONObject result = requestCommand(httpCommand);
            if (result == null) {
                return response;//请求失败
            }
            this.shuttleProtocol.setSendTime(System.currentTimeMillis());//指令下发时间
            response.setMessage(JSON.toJSONString(result));
            response.setResult(true);
            return response;
        } catch (Exception e) {
            e.printStackTrace();
            return response;
        }
    }
    @Override
    public CommandResponse reset(ShuttleCommand command) {
        setSyncTaskNo(0);
        setProtocolStatus(ShuttleProtocolStatusType.IDLE);
        enableMoveLoc(null, false);
        return new CommandResponse(true, JSON.toJSONString(command));
    }
    @Override
    public CommandResponse updateLocation(ShuttleCommand command) {
        CommandResponse response = new CommandResponse(false);
        try {
            //发出请求
            NyShuttleHttpCommand httpCommand = JSON.parseObject(command.getBody(), NyShuttleHttpCommand.class);
            JSONObject result = requestCommand(httpCommand);
            if (result == null) {
                return response;//请求失败
            }
            this.shuttleProtocol.setSendTime(System.currentTimeMillis());//指令下发时间
            response.setMessage(JSON.toJSONString(result));
            response.setResult(true);
            return response;
        } catch (Exception e) {
            e.printStackTrace();
            return response;
        }
    }
    @Override
    public boolean isIdle() {
        return this.isIdle(null);
    }
    @Override
    public boolean isIdle(ExecuteSupport support) {
        if (null != support) {
            Boolean judgement = support.judgement();
            if (judgement != null && !judgement) {
                return true;
            }
        }
        if (this.shuttleProtocol.getDeviceStatus() == null
                || this.shuttleProtocol.getPakMk() == null
                || this.shuttleProtocol.getErrorCode() == null
                || this.shuttleProtocol.getProtocolStatus() == null
                || this.shuttleProtocol.getMode() == null
                || this.shuttleProtocol.getExtend() == null
        ) {
            return false;
        }
        InnerSuhttleExtend extend = (InnerSuhttleExtend) this.shuttleProtocol.getExtend();
        boolean res = this.shuttleProtocol.getDeviceStatus() == 1
                && this.shuttleProtocol.getMode() == 1
                && this.shuttleProtocol.getPakMk()
                && this.shuttleProtocol.getErrorCode().equals("0")
                && (this.shuttleProtocol.getProtocolStatus() == ShuttleProtocolStatusType.IDLE.id
                || this.shuttleProtocol.getProtocolStatus() == ShuttleProtocolStatusType.WAITING.id
                || this.shuttleProtocol.getProtocolStatus() == ShuttleProtocolStatusType.CHARGING_WAITING.id)
                && extend.getSuspendState() == 0;
        return res;
    }
    @Override
    public boolean isDeviceIdle() {
        return isDeviceIdle(null);
    }
    @Override
    public boolean isDeviceIdle(ExecuteSupport support) {
        if (null != support) {
            Boolean judgement = support.judgement();
            if (judgement != null && !judgement) {
                return true;
            }
        }
        if (this.shuttleProtocol.getDeviceStatus() == null
                || this.shuttleProtocol.getPakMk() == null
                || this.shuttleProtocol.getErrorCode() == null
                || this.shuttleProtocol.getMode() == null
                || this.shuttleProtocol.getExtend() == null
        ) {
            return false;
        }
        InnerSuhttleExtend extend = (InnerSuhttleExtend) this.shuttleProtocol.getExtend();
        boolean res = this.shuttleProtocol.getDeviceStatus() == 1
                && this.shuttleProtocol.getMode() == 1
                && this.shuttleProtocol.getPakMk()
                && this.shuttleProtocol.getErrorCode().equals("0")
                && extend.getSuspendState() == 0
                ;
        return res;
    }
    @Override
    public boolean isRequireCharge() {
        if (this.shuttleProtocol.getDeviceStatus() == null
                || this.shuttleProtocol.getPakMk() == null
                || this.shuttleProtocol.getErrorCode() == null
                || this.shuttleProtocol.getProtocolStatus() == null
                || this.shuttleProtocol.getMode() == null
                || this.shuttleProtocol.getExtend() == null
        ) {
            return false;
        }
        InnerSuhttleExtend extend = (InnerSuhttleExtend) this.shuttleProtocol.getExtend();
        boolean res = this.shuttleProtocol.getDeviceStatus() == 1
                && this.shuttleProtocol.getMode() == 1
                && this.shuttleProtocol.getPakMk()
                && this.shuttleProtocol.getErrorCode().equals("0")
                && this.shuttleProtocol.getProtocolStatus() == ShuttleProtocolStatusType.IDLE.id
                && extend.getSuspendState() == 0
                ;
        if (!res) {
            return res;
        } else {
            // 电量小于阈值需要进行充电
            try {
                BasShuttleService shuttleService = SpringUtils.getBean(BasShuttleService.class);
                if (shuttleService == null) {
                    return false;
                }
                BasShuttle basShuttle = shuttleService.selectOne(new EntityWrapper<BasShuttle>().eq("shuttle_no", slave.getId()));
                if (basShuttle == null) {
                    return false;
                }
                Integer chargeLine = basShuttle.getChargeLine();
                if (chargeLine == null) {
                    return false;
                }
                return Integer.valueOf(this.shuttleProtocol.getBatteryPower()) < chargeLine;
            } catch (Exception e) {
                return false;
            }
        }
    }
    @Override
    public boolean isCharging() {
        if (this.shuttleProtocol.getDeviceStatus() == null || this.shuttleProtocol.getHasCharge() == null) {
            return false;
        }
        if (this.shuttleProtocol.getDeviceStatus() == 0 && this.shuttleProtocol.getHasCharge()) {
            //运行中 && 充电中
            return true;
        }
        return false;
    }
    @Override
    public boolean isChargingCompleted() {
        Integer maxPower = 100;
        ConfigService configService = SpringUtils.getBean(ConfigService.class);
        if (configService != null) {
            Config chargeMaxValue = configService.selectOne(new EntityWrapper<Config>()
                    .eq("code", "chargeMaxValue")
                    .eq("status", 1));
            if (chargeMaxValue != null) {
                maxPower = Integer.parseInt(chargeMaxValue.getValue());
            }
        }
        if (this.shuttleProtocol.getHasCharge() == null) {
            return false;
        }
        if (this.shuttleProtocol.getBatteryPower() == null) {
            return false;
        }
        if (!this.shuttleProtocol.getHasCharge()) {
            return false;
        }
        if (Integer.valueOf(this.shuttleProtocol.getBatteryPower()) >= maxPower) {
            return true;
        }
        return false;
    }
    @Override
    public List<NavigateNode> getMoveAdvancePath() {
        ObjectMapper objectMapper = SpringUtils.getBean(ObjectMapper.class);
        NavigateMapData navigateMapData = SpringUtils.getBean(NavigateMapData.class);
        ArrayList<NavigateNode> path = new ArrayList<>();
        if (shuttleProtocol.getTaskNo() != 0) {
            //存在任务,获取指令
            Object object = redisUtil.get(RedisKeyType.SHUTTLE.key + shuttleProtocol.getTaskNo());
            if (object != null) {
                ShuttleRedisCommand redisCommand = null;
                try {
                    redisCommand = objectMapper.readValue(String.valueOf(object), ShuttleRedisCommand.class);
                } catch (IOException e) {
                    return path;
                }
                List<NavigateNode> nodes = redisCommand.getAssignCommand().getNodes();//穿梭车预计路径
                if (nodes == null) {
                    return path;
                }
                if (!nodes.isEmpty()) {
                    path.addAll(nodes);
                }
                NavigateNode navigateNode = path.get(0);
                int lev = navigateNode.getZ();
                //将路径锁与小车路径进行匹配
                ArrayList<NavigateNode> tmp = new ArrayList<>();
                //检测路径是否被锁定
                int[][] map = navigateMapData.getDataFromRedis(lev, NavigationMapType.DFX.id, null, null);
                for (NavigateNode node : path) {
                    if(map[node.getX()][node.getY()] == -999) {
                        tmp.add(node);
                    }
                }
                path = tmp;
            }
        }
        return path;
    }
    @Override
    public int generateDeviceTaskNo(int taskNo, ShuttleTaskNoType type) {
        return taskNo;
    }
    @Override
    public synchronized boolean setProtocolStatus(ShuttleProtocolStatusType status) {
        this.shuttleProtocol.setProtocolStatus(status);
        return true;
    }
    @Override
    public synchronized boolean setTaskNo(Integer taskNo) {
        this.shuttleProtocol.setTaskNo(taskNo);
        return true;
    }
    @Override
    public synchronized boolean setSyncTaskNo(Integer taskNo) {
        this.shuttleProtocol.setSyncTaskNo(taskNo);
        return true;
    }
    @Override
    public synchronized boolean setPakMk(boolean pakMk) {
        this.shuttleProtocol.setPakMk(pakMk);
        return true;
    }
    @Override
    public boolean enableMoveLoc(ShuttleMoveLocParam param, boolean enable) {
        if (enable) {
            shuttleProtocol.setMoveLoc(true);//开启跑库
            shuttleProtocol.setMoveType(param.getMoveType());
            shuttleProtocol.setXStart(param.getStartX());
            shuttleProtocol.setXTarget(param.getTargetX());
            shuttleProtocol.setXCurrent(param.getStartX());
            shuttleProtocol.setYStart(param.getStartY());
            shuttleProtocol.setYTarget(param.getTargetY());
            shuttleProtocol.setYCurrent(param.getStartY());
        }else {
            shuttleProtocol.setMoveLoc(false);
            shuttleProtocol.setMoveType(0);
            shuttleProtocol.setXStart(0);
            shuttleProtocol.setXTarget(0);
            shuttleProtocol.setXCurrent(0);
            shuttleProtocol.setYStart(0);
            shuttleProtocol.setYTarget(0);
            shuttleProtocol.setYCurrent(0);
        }
        return true;
    }
    @Override
    public boolean requestWaiting() {
        if (this.shuttleProtocol.getProtocolStatusType().equals(ShuttleProtocolStatusType.IDLE)) {
            this.shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.WAITING);
            return true;
        }
        return false;
    }
    @Override
    public ShuttleCommand getMoveCommand(Integer taskNo, String startCodeNum, String distCodeNum, Integer allDistance, Integer runDirection, Integer runSpeed, List<NavigateNode> nodes) {
        NavigateMapData navigateMapData = SpringUtils.getBean(NavigateMapData.class);
        NyShuttleHttpCommand httpStandard = getHttpStandard(slave.getId(), taskNo);
        NyShuttleHttpCommand.NyRequest request = httpStandard.getRequest();
        ArrayList<HashMap<String, Object>> path = new ArrayList<>();
        Integer taskId = getTaskId();
        HashMap<String, Object> body = new HashMap<>();
        body.put("requestType", "move");//移动命令
        body.put("taskId", taskId);//TaskID需要随机
//        body.put("start", navigateNodeToNyPointNode(NavigatePositionConvert.codeToNode(startCodeNum, device.getHostId())));//起点
//        body.put("target", navigateNodeToNyPointNode(NavigatePositionConvert.codeToNode(distCodeNum, device.getHostId())));//终点
        body.put("path", path);
        request.setBody(body);
        NavigateNode startNode = nodes.get(0);
        for (NavigateNode node : nodes) {
            HashMap<String, Object> data = new HashMap<>();
            String codeNum = NavigatePositionConvert.xyToPosition(node.getX(), node.getY(), node.getZ());
            Map<String, Object> nyNode = navigateNodeToNyPointNode(NavigatePositionConvert.codeToNode(codeNum));
            int xp = Integer.parseInt(String.valueOf(nyNode.get("y")));
            int yp = Integer.parseInt(String.valueOf(nyNode.get("x")));
            int z = Integer.parseInt(String.valueOf(nyNode.get("z")));
            List<List<MapNode>> mapData = navigateMapData.getJsonData(startNode.getZ(), NavigationMapType.NONE.id, null, null);
            List<MapNode> mapNodes = mapData.get(node.getX());
            MapNode mapNode = mapNodes.get(node.getY());
            data.put("xp", xp);
            data.put("yp", yp);
            data.put("z", z);
            data.put("x", mapNode.getYBase());
            data.put("y", mapNode.getXBase());
            path.add(data);
        }
        httpStandard.setRequest(request);
        LocMastService locMastService = SpringUtils.getBean(LocMastService.class);
        LocMast locMast = locMastService.selectOne(new EntityWrapper<LocMast>()
                .eq("code", distCodeNum));
        if (locMast == null) {
            throw new CoolException("库位信息不存在");
        }
        ShuttleCommand command = new ShuttleCommand();
        command.setShuttleNo(slave.getId());
        command.setBody(JSON.toJSONString(httpStandard));
        command.setMode(ShuttleCommandModeType.MOVE.id);
        command.setTargetLocNo(locMast.getLocNo());
        command.setTaskNo(taskId);
        return command;
    }
    @Override
    public ShuttleCommand getLiftCommand(Integer taskNo, Boolean lift) {
        NyShuttleHttpCommand httpStandard = getHttpStandard(slave.getId(), taskNo);
        NyShuttleHttpCommand.NyRequest request = httpStandard.getRequest();
        Integer taskId = getTaskId();//TaskID需要随机
        HashMap<String, Object> body = new HashMap<>();
        body.put("requestType", lift ? "liftUp" : "liftDown");//顶升或下降命令
        body.put("taskId", taskId);
        request.setBody(body);
        httpStandard.setRequest(request);
        ShuttleCommand command = new ShuttleCommand();
        command.setShuttleNo(slave.getId());
        command.setBody(JSON.toJSONString(httpStandard));
        command.setMode(lift ? ShuttleCommandModeType.PALLET_LIFT.id : ShuttleCommandModeType.PALLET_DOWN.id);
        command.setTaskNo(taskId);
        return command;
    }
    @Override
    public ShuttleCommand getChargeCommand(Integer taskNo, Boolean charge) {
        NyShuttleHttpCommand httpStandard = getHttpStandard(slave.getId(), taskNo);
        NyShuttleHttpCommand.NyRequest request = httpStandard.getRequest();
        Integer taskId = getTaskId();//TaskID需要随机
        HashMap<String, Object> body = new HashMap<>();
        body.put("requestType", charge ? "charge" : "stopCharge");//充电或停止充电
        body.put("taskId", taskId);
        request.setBody(body);
        httpStandard.setRequest(request);
        ShuttleCommand command = new ShuttleCommand();
        command.setShuttleNo(slave.getId());
        command.setBody(JSON.toJSONString(httpStandard));
        command.setMode(charge ? ShuttleCommandModeType.CHARGE_OPEN.id : ShuttleCommandModeType.CHARGE_CLOSE.id);
        command.setTaskNo(taskId);
        return command;
    }
    @Override
    public ShuttleCommand getUpdateLocationCommand(Integer taskNo, String locNo) {
        NyShuttleHttpCommand httpStandard = getHttpStandard(slave.getId(), taskNo);
        NyShuttleHttpCommand.NyRequest request = httpStandard.getRequest();
        HashMap<String, Object> body = new HashMap<>();
        body.put("requestType", "updateFloor");//更新层Z
        body.put("z", Utils.getLev(locNo));//坐标Z
        request.setBody(body);
        httpStandard.setRequest(request);
        ShuttleCommand command = new ShuttleCommand();
        command.setShuttleNo(slave.getId());
        command.setBody(JSON.toJSONString(httpStandard));
        command.setMode(ShuttleCommandModeType.UPDATE_LOCATION.id);
        command.setTaskNo(taskNo);
        return command;
    }
    //获取小车复位响应命令
    public ShuttleCommand getInitCommand(Integer taskNo, Integer code) {
        LocMastService locMastService = SpringUtils.getBean(LocMastService.class);
        NavigateMapData navigateMapData = SpringUtils.getBean(NavigateMapData.class);
        NyShuttleHttpCommand httpStandard = getHttpStandard(slave.getId(), taskNo);
        NyShuttleHttpCommand.NyRequest request = httpStandard.getRequest();
        //code -> {Integer@13781} 1101101
        int lev = code % 100;
        int bay = code / 100 % 1000;
        int row = code / 100000;
        HashMap<String, Object> map = new HashMap<>();
        map.put("x", row);
        map.put("y", bay);
        map.put("z", lev);
        String mapStr = JSON.toJSONString(map);
        LocMast locMast = locMastService.selectOne(new EntityWrapper<LocMast>()
                .eq("code", mapStr)
                .eq("status", 1));
        if (locMast == null) {
            throw new CoolException("地址码不存在");
        }
        List<List<MapNode>> mapData = navigateMapData.getJsonData(lev, NavigationMapType.NONE.id, null, null);
        List<MapNode> mapNodes = mapData.get(locMast.getRow1());
        MapNode mapNode = mapNodes.get(locMast.getBay1());
        HashMap<String, Object> location = new HashMap<>();
        location.put("xp", row);
        location.put("yp", bay);
        location.put("z", lev);
        location.put("x", mapNode.getYBase());
        location.put("y", mapNode.getXBase());
        HashMap<String, Object> body = new HashMap<>();
        body.put("responseType", "init");//复位
        body.put("location", location);//初始化坐标
        body.put("devicePoints", new ArrayList<>());//提升机点位
        body.put("specialPoints", new ArrayList<>());//特殊条码坐标
        request.setBody(body);
        httpStandard.setRequest(request);
        ShuttleCommand command = new ShuttleCommand();
        command.setShuttleNo(slave.getId());
        command.setBody(JSON.toJSONString(httpStandard));
        command.setMode(ShuttleCommandModeType.RESET.id);
        command.setTaskNo(taskNo);
        return command;
    }
    @Override
    public boolean connect() {
        try {
            Socket socket = new Socket(slave.getIp(), slave.getPort());
            socket.setSoTimeout(10000);
            socket.setKeepAlive(true);
            this.socket = socket;
            log.info(MessageFormat.format("【{0}】四向穿梭车Socket链接成功 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
        } catch (IOException e) {
            OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车Socket链接失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
            return false;
        }
        return true;
    }
    @Override
    public void close() {
    }
    //获取HTTP请求标准结构体
    private NyShuttleHttpCommand getHttpStandard(Integer shuttleNo, Integer taskNo) {
        NyShuttleHttpCommand httpStandard = new NyShuttleHttpCommand();
        httpStandard.setMsgType("requestMsg");//请求消息
        httpStandard.setRobotId(shuttleNo);//车辆编号
        httpStandard.setTaskNo(taskNo);//工作号
        //设置请求消息
        NyShuttleHttpCommand.NyRequest request = new NyShuttleHttpCommand.NyRequest();
        NyShuttleHttpCommand.NyRequest.NyHeader header = new NyShuttleHttpCommand.NyRequest.NyHeader();
        header.setVersion("1.0");//版本号
        header.setRequestId(getRequestId());//消息编号
        //设置请求头
        request.setHeader(header);
        httpStandard.setRequest(request);
        return httpStandard;
    }
    //获取请求编号
    private Integer getRequestId() {
        Random random = new Random();
        return random.nextInt(9999999);
    }
    //获取TaskId
    private static Integer getTaskId() {
        Random random = new Random();
        return random.nextInt(999999);
    }
    //获取读FAS状态信息命令
    private NyShuttleHttpCommand getReadStatusCommand(Integer shuttleNo) {
        NyShuttleHttpCommand httpStandard = getHttpStandard(shuttleNo, 9999);
        NyShuttleHttpCommand.NyRequest request = httpStandard.getRequest();
        HashMap<String, Object> body = new HashMap<>();
        body.put("requestType", "readState");//读FAS状态信息
        request.setBody(body);
        httpStandard.setRequest(request);
        return httpStandard;
    }
    //发出请求
    private JSONObject requestCommand(NyShuttleHttpCommand httpCommand) throws IOException {
        if (this.socket == null) {
            return null;
        }
        //压缩数据包
        JSONObject data = JSON.parseObject(JSON.toJSONString(httpCommand));
        data.remove("nodes");
        // 获取输出流
        OutputStreamWriter writer = new OutputStreamWriter(this.socket.getOutputStream());
        writer.write(JSON.toJSONString(data) + "\r\n");
        writer.flush();
//            System.out.println("Sent message to server: " + JSON.toJSONString(httpCommand));
        String requestType = null;
        try {
            requestType = httpCommand.getRequest().getBody().get("requestType").toString();
        } catch (Exception e) {
            return null;
        }
        // 获取服务器响应
        // 尝试10次
        JSONObject result = null;
        for (int i = 0; i < 10; i++) {
            result = getRequestBody(requestType);
            if (result == null) {
                try {
                    Thread.sleep(100);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }else {
                break;
            }
        }
        return result;//返回Body结果集
    }
    private JSONObject filterBodyData(JSONObject data) {
        Object response = data.get("response");
        if (response == null) {
            return null;
        }
        JSONObject result = JSON.parseObject(response.toString());
        Object body = result.get("body");
        if (body == null) {
            return null;
        }
        JSONObject jsonBody = JSON.parseObject(body.toString());
        return jsonBody;
    }
    //地图节点转换牛眼节点
    private static Map<String, Object> navigateNodeToNyPointNode(NavigateNode node) {
        int[] NyPosition = WCSXyzToNyXyz(node.getX(), node.getY(), node.getZ());//WCS系统坐标转牛眼坐标
        HashMap<String, Object> point = new HashMap<>();
        point.put("x", NyPosition[0]);
        point.put("y", NyPosition[1]);
        point.put("z", NyPosition[2]);
        return point;
    }
    //WCS系统坐标转牛眼坐标
    private static int[] WCSXyzToNyXyz(int x, int y, int z) {
//        //WCS系统Y轴 => 牛眼X轴转换公式
//        int x1 = Math.abs(y - 61) + 11;
//        //WCS系统X轴 => 牛眼Y轴转换公式
//        int y1 = x + 10;
        int x1 = x + 10;
        int y1 = y + 10;
        return new int[]{y1, x1, z};
    }
    @Data
    private class InnerSuhttleExtend {
        /**
         * 管制状态不在管制下/被管制中
         * 0/1
         */
        private Integer suspendState;
        /**
         * 当前速度,单位mm/s
         */
        private Integer speed;
        /**
         * 剩余电量/10(A)
         */
        private Integer surplusQuantity;
        /**
         * 总电量/10(A)
         */
        private Integer countQuantity;
    }
}
src/main/java/com/zy/core/thread/impl/ZyForkLiftThread.java
New file
@@ -0,0 +1,277 @@
package com.zy.core.thread.impl;
import HslCommunication.Core.Types.OperateResultExOne;
import HslCommunication.Profinet.Siemens.SiemensS7Net;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.DateUtils;
import com.core.common.SpringUtils;
import com.zy.asrs.entity.BasLift;
import com.zy.asrs.entity.DeviceDataLog;
import com.zy.asrs.service.BasLiftService;
import com.zy.asrs.service.DeviceDataLogService;
import com.zy.asrs.utils.Utils;
import com.zy.common.ExecuteSupport;
import com.zy.common.utils.RedisUtil;
import com.zy.core.News;
import com.zy.core.cache.OutputQueue;
import com.zy.core.enums.ForkLiftProtocolStatusType;
import com.zy.core.enums.ForkLiftTaskModeType;
import com.zy.core.model.CommandResponse;
import com.zy.core.model.ForkLiftSlave;
import com.zy.core.model.command.ForkLiftCommand;
import com.zy.core.model.protocol.ForkLiftProtocol;
import com.zy.core.model.protocol.ForkLiftStaProtocol;
import com.zy.core.thread.ForkLiftThread;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.text.MessageFormat;
import java.util.*;
@Slf4j
@SuppressWarnings("all")
public class ZyForkLiftThread implements ForkLiftThread {
    private ForkLiftSlave slave;
    private ForkLiftProtocol forkLiftProtocol;
    private RedisUtil redisUtil;
    private SiemensS7Net siemensS7Net;
    private List<ForkLiftStaProtocol> forkLiftStaProtocols = new ArrayList<>();
    public ZyForkLiftThread(ForkLiftSlave slave, RedisUtil redisUtil) {
        this.slave = slave;
        this.redisUtil = redisUtil;
        //初始化站点
        for (ForkLiftSlave.Sta sta : this.slave.getSta()) {
            ForkLiftStaProtocol forkLiftStaProtocol = new ForkLiftStaProtocol();
            forkLiftStaProtocol.setStaNo(sta.getStaNo());//站点号
            forkLiftStaProtocol.setLev(sta.getLev());//站点楼层
            String locNo = Utils.getLocNo(this.slave.getStaRow(), this.slave.getStaBay(), sta.getLev());
            forkLiftStaProtocol.setLocNo(locNo);//站点库位号
            forkLiftStaProtocol.setLiftNo(sta.getLiftNo());//提升机号
            forkLiftStaProtocols.add(forkLiftStaProtocol);
        }
    }
    @Override
    public boolean connect() {
        return false;
    }
    @Override
    public void close() {
    }
    @Override
    public void run() {
        News.info("{}号货叉提升机线程启动", slave.getId());
        this.connect();
        while (true) {
            try {
                read();
                Thread.sleep(200);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    private void read() {
        try {
            readStatus();
            //提升机处于运行状态,将标记置为true
            if (forkLiftProtocol.getProtocolStatusType().equals(ForkLiftProtocolStatusType.PICK_UP)
                    || forkLiftProtocol.getProtocolStatusType().equals(ForkLiftProtocolStatusType.PUT_DOWN)
                    || forkLiftProtocol.getProtocolStatusType().equals(ForkLiftProtocolStatusType.WAITING)) {
                forkLiftProtocol.setPakMk(true);
            }
        } catch (Exception e) {
            OutputQueue.FORKLIFT.offer(MessageFormat.format("【{0}】读取提升机状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
        }
    }
    private void readStatus() {
        try {
            //获取提升机数据
            OperateResultExOne<byte[]> result1 = siemensS7Net.Read("DB101.0", (short) 32);
            if (result1.IsSuccess) {
                if (null == forkLiftProtocol) {
                    forkLiftProtocol = new ForkLiftProtocol();
                    forkLiftProtocol.setLiftNo(slave.getId());
                    forkLiftProtocol.setProtocolStatus(ForkLiftProtocolStatusType.NONE);
                    InnerForkLiftExtend innerForkLiftExtend = new InnerForkLiftExtend();
                }
                //----------读取提升机状态-----------
                //模式
                forkLiftProtocol.setModel((int) siemensS7Net.getByteTransform().TransInt16(result1.Content, 0));
                //任务号
                forkLiftProtocol.setTaskNo((int) siemensS7Net.getByteTransform().TransInt16(result1.Content, 4));
                //任务状态
                forkLiftProtocol.setProtocolStatus((int) siemensS7Net.getByteTransform().TransInt16(result1.Content, 8));
                //任务模式
                forkLiftProtocol.setModel((int) siemensS7Net.getByteTransform().TransInt16(result1.Content, 12));
                //取货数据
                forkLiftProtocol.setPick((int) siemensS7Net.getByteTransform().TransInt16(result1.Content, 16));
                //放货数据
                forkLiftProtocol.setPut((int) siemensS7Net.getByteTransform().TransInt16(result1.Content, 20));
                //出入库模式
                forkLiftProtocol.setIOMode((int) siemensS7Net.getByteTransform().TransInt16(result1.Content, 24));
                //故障码
                forkLiftProtocol.setErrorCode((int) siemensS7Net.getByteTransform().TransInt16(result1.Content, 28));
                //************补充扩展字段*************
                InnerForkLiftExtend forkLiftExtend = (InnerForkLiftExtend) forkLiftProtocol.getExtend();
                forkLiftProtocol.setExtend(forkLiftExtend);
            }else {
                OutputQueue.FORKLIFT.offer(MessageFormat.format("【{0}】{1}读取货叉提升机状态信息失败", DateUtils.convert(new Date()), slave.getId()));
            }
            if (System.currentTimeMillis() - forkLiftProtocol.getDeviceDataLog() > 1000 * 5) {
                //采集时间超过5s,保存一次数据记录
                //保存数据记录
                DeviceDataLogService deviceDataLogService = SpringUtils.getBean(DeviceDataLogService.class);
                DeviceDataLog deviceDataLog = new DeviceDataLog();
                deviceDataLog.setOriginData(Base64.getEncoder().encodeToString(result1.Content));
                deviceDataLog.setWcsData(JSON.toJSONString(forkLiftProtocol));
                deviceDataLog.setType("forkLift");
                deviceDataLog.setDeviceNo(forkLiftProtocol.getLiftNo());
                deviceDataLog.setCreateTime(new Date());
                deviceDataLogService.insert(deviceDataLog);
                //更新采集时间
                forkLiftProtocol.setDeviceDataLog(System.currentTimeMillis());
            }
            //将提升机状态保存至数据库
            BasLiftService basLiftService = SpringUtils.getBean(BasLiftService.class);
            BasLift basLift = basLiftService.selectOne(new EntityWrapper<BasLift>()
                    .eq("lift_no", slave.getId()));
            if (basLift == null) {
                basLift = new BasLift();
                //提升机号
                basLift.setLiftNo(forkLiftProtocol.getLiftNo());
                basLift.setStatus(1);
                basLiftService.insert(basLift);
            }
            //任务号
            basLift.setWrkNo(forkLiftProtocol.getTaskNo());
            //修改时间
            basLift.setUpdateTime(new Date());
            //设备状态
            basLift.setDeviceStatus(JSON.toJSONString(forkLiftProtocol));
            if (basLiftService.updateById(basLift)) {
                OutputQueue.FORKLIFT.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), forkLiftProtocol.getLiftNo()));
            }
        } catch (Exception e) {
            OutputQueue.FORKLIFT.offer(MessageFormat.format("【{0}】读取货叉提升机状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
        }
    }
    @Override
    public ForkLiftProtocol getStatus(boolean clone) {
        if (this.forkLiftProtocol == null) {
            return null;
        }
        return clone ? this.forkLiftProtocol.clone() : this.forkLiftProtocol;
    }
    @Override
    public List<ForkLiftStaProtocol> getForkLiftStaProtocols() {
        return this.forkLiftStaProtocols;
    }
    @Override
    public ForkLiftProtocol getStatus() {
        return getStatus(true);
    }
    @Override
    public CommandResponse pickAndPut(ForkLiftCommand command) {
        return null;
    }
    @Override
    public CommandResponse shuttleSwitch(ForkLiftCommand command) {
        return null;
    }
    @Override
    public CommandResponse reset(ForkLiftCommand command) {
        return null;
    }
    @Override
    public boolean isIdle() {
        return false;
    }
    @Override
    public boolean isDeviceIdle() {
        return false;
    }
    @Override
    public boolean isDeviceIdle(ExecuteSupport support) {
        return false;
    }
    @Override
    public boolean setProtocolStatus(ForkLiftProtocolStatusType status) {
        return false;
    }
    @Override
    public boolean setSyncTaskNo(Integer taskNo) {
        return false;
    }
    @Override
    public int generateDeviceTaskNo(int taskNo, ForkLiftTaskModeType type) {
        return 0;
    }
    @Override
    public List<ForkLiftCommand> getPickAndPutCommand(Integer taskNo, Integer pick, Integer put) {
        List<ForkLiftCommand> commands = new ArrayList<>();
        ForkLiftCommand command = new ForkLiftCommand();
        command.setLiftNo(slave.getId());
        command.setTaskNo(taskNo.shortValue());
        command.setMode(ForkLiftTaskModeType.PICK_PUT.id.shortValue());
        command.setPick(pick.shortValue());
        command.setPut(put.shortValue());
        command.setConfirm((short) 1);
        commands.add(command);
        return commands;
    }
    @Override
    public List<ForkLiftCommand> getShuttleSwitchCommand(Integer taskNo, Integer originLev, Integer targetLev) {
        List<ForkLiftCommand> commands = new ArrayList<>();
        ForkLiftCommand command = new ForkLiftCommand();
        command.setLiftNo(slave.getId());
        command.setTaskNo(taskNo.shortValue());
        command.setMode(ForkLiftTaskModeType.SHUTTLE_SWITCH.id.shortValue());
        command.setPick(originLev.shortValue());
        command.setPut(targetLev.shortValue());
        command.setConfirm((short) 1);
        commands.add(command);
        return commands;
    }
    /**
     * 扩展字段
     */
    @Data
    private class InnerForkLiftExtend {
    }
}
src/main/resources/application.yml
@@ -42,9 +42,11 @@
wms:
  url: 10.10.10.40:8080/tzskwms
pythonCalcPath: D:\\path\\cpu.py
pythonCalcSimilarity: D:\\path\\similarity.py
# 下位机配置
wcs-slave:
  # 输送线
  devp[0]:
    id: 1
@@ -58,28 +60,28 @@
      backSta: 101
      barcode: ${wcs-slave.barcode[0].id}
      led: ${wcs-slave.led[1].id}
      liftNo: ${wcs-slave.lift[0].id}
      liftNo: ${wcs-slave.forkLift[0].id}
    # 入库口2
    inSta[1]:
      staNo: 103
      backSta: 102
      barcode: ${wcs-slave.barcode[1].id}
      led: ${wcs-slave.led[2].id}
      liftNo: ${wcs-slave.lift[0].id}
      liftNo: ${wcs-slave.forkLift[0].id}
    # 空板入库口1
    emptyInSta[0]:
      staNo: 100
      backSta: 101
      barcode: ${wcs-slave.barcode[0].id}
      led: ${wcs-slave.led[1].id}
      liftNo: ${wcs-slave.lift[0].id}
      liftNo: ${wcs-slave.forkLift[0].id}
    # 空板入库口2
    emptyInSta[1]:
      staNo: 103
      backSta: 102
      barcode: ${wcs-slave.barcode[1].id}
      led: ${wcs-slave.led[2].id}
      liftNo: ${wcs-slave.lift[0].id}
      liftNo: ${wcs-slave.forkLift[0].id}
    # 出库口1
    outSta[0]:
      staNo: 100
@@ -94,13 +96,13 @@
      backSta: 100
      barcode: ${wcs-slave.barcode[0].id}
      led: ${wcs-slave.led[1].id}
      liftNo: ${wcs-slave.lift[0].id}
      liftNo: ${wcs-slave.forkLift[0].id}
    pickInSta[1]:
      staNo: 103
      backSta: 103
      barcode: ${wcs-slave.barcode[1].id}
      led: ${wcs-slave.led[2].id}
      liftNo: ${wcs-slave.lift[0].id}
      liftNo: ${wcs-slave.forkLift[0].id}
  # 条码扫描仪
  barcode[0]:
@@ -156,8 +158,8 @@
    port: 8888
    rack: 0
    slot: 0
  # 提升机1
  lift[0]:
  # 货叉提升机1
  forkLift[0]:
    id: 1
    ip: 10.10.10.131
    port: 102
@@ -166,40 +168,20 @@
    sta[0]:
      staNo: 101
      lev: 1
      liftNo: ${wcs-slave.lift[0].id}
      liftNo: ${wcs-slave.forkLift[0].id}
    sta[1]:
      staNo: 102
      lev: 2
      liftNo: ${wcs-slave.lift[0].id}
      liftNo: ${wcs-slave.forkLift[0].id}
    sta[2]:
      staNo: 103
      lev: 3
      liftNo: ${wcs-slave.lift[0].id}
      liftNo: ${wcs-slave.forkLift[0].id}
    sta[3]:
      staNo: 104
      lev: 4
      liftNo: ${wcs-slave.lift[0].id}
      liftNo: ${wcs-slave.forkLift[0].id}
    sta[4]:
      staNo: 105
      lev: 5
      liftNo: ${wcs-slave.lift[0].id}
    sta[5]:
      staNo: 106
      lev: 6
      liftNo: ${wcs-slave.lift[0].id}
    sta[6]:
      staNo: 107
      lev: 7
      liftNo: ${wcs-slave.lift[0].id}
    sta[7]:
      staNo: 108
      lev: 8
      liftNo: ${wcs-slave.lift[0].id}
    sta[8]:
      staNo: 109
      lev: 9
      liftNo: ${wcs-slave.lift[0].id}
    sta[9]:
      staNo: 110
      lev: 10
      liftNo: ${wcs-slave.lift[0].id}
      liftNo: ${wcs-slave.forkLift[0].id}
src/main/resources/mapper/BasCrnErrorMapper.xml
File was deleted
src/main/resources/mapper/BasCrnpMapper.xml
File was deleted
src/main/resources/mapper/BasMapMapper.xml
@@ -14,10 +14,11 @@
    </resultMap>
    <select id="selectLatestMap" resultMap="BaseResultMap">
        select top 1 *
        select *
        from asr_bas_map
        where lev = #{lev}
        order by id desc
        limit 0,1
    </select>
    <delete id="deleteByLev">
src/main/resources/mapper/BasShuttleMapper.xml
@@ -16,49 +16,11 @@
        <result column="update_by" property="updateBy" />
        <result column="update_time" property="updateTime" />
        <result column="memo" property="memo" />
        <result column="lift_no" property="liftNo" />
        <result column="pak_mk" property="pakMk" />
<!--        <result column="busy_status" property="busyStatus" />-->
<!--        <result column="current_code" property="currentCode" />-->
<!--        <result column="battery_power" property="batteryPower" />-->
<!--        <result column="battery_temp" property="batteryTemp" />-->
<!--        <result column="error_code" property="errorCode" />-->
<!--        <result column="plc_output_status_io" property="plcOutputStatusIo" />-->
<!--        <result column="status_error_code" property="statusErrorCode" />-->
<!--        <result column="plc_input_status" property="plcInputStatus" />-->
<!--        <result column="current_or_before_code" property="currentOrBeforeCode" />-->
<!--        <result column="code_offset_x" property="codeOffsetX" />-->
<!--        <result column="code_offset_y" property="codeOffsetY" />-->
<!--        <result column="current_voltage" property="currentVoltage" />-->
<!--        <result column="current_analog_value" property="currentAnalogValue" />-->
<!--        <result column="current_lift_servo_speed" property="currentLiftServoSpeed" />-->
<!--        <result column="current_move_servo_speed" property="currentMoveServoSpeed" />-->
<!--        <result column="current_lift_servo_load" property="currentLiftServoLoad" />-->
<!--        <result column="current_move_servo_load" property="currentMoveServoLoad" />-->
        <result column="working_mode" property="workingMode" />
        <result column="free" property="free" />
        <result column="speed" property="speed" />
        <result column="load_state" property="loadState" />
        <result column="suspend_state" property="suspendState" />
        <result column="lift_position" property="liftPosition" />
        <result column="run_dir" property="runDir" />
        <result column="run_dir2" property="runDir2" />
        <result column="charg_state" property="chargState" />
        <result column="power_percent" property="powerPercent" />
        <result column="max_cell_voltage" property="maxCellVoltage" />
        <result column="min_cell_voltage" property="minCellVoltage" />
        <result column="voltage" property="voltage" />
        <result column="charge_cycle_times" property="chargeCycleTimes" />
        <result column="surplus_quantity" property="surplusQuantity" />
        <result column="count_quantity" property="countQuantity" />
        <result column="point" property="point" />
        <result column="coord" property="coord" />
        <result column="task" property="task" />
        <result column="task_state" property="taskState" />
        <result column="err_state" property="errState" />
        <result column="status_sum" property="statusSum" />
        <result column="err_time" property="errTime" />
        <result column="run_speed" property="runSpeed" />
        <result column="device_status" property="deviceStatus" />
        <result column="disable_lev" property="disableLev" />
    </resultMap>
src/main/resources/mapper/BasSteErrLogMapper.xml
File was deleted
src/main/resources/mapper/BasSteErrMapper.xml
File was deleted
src/main/resources/mapper/BasSteMapper.xml
File was deleted
src/main/resources/mapper/BasSteOptMapper.xml
File was deleted
src/main/resources/mapper/LocMastMapper.xml
@@ -5,68 +5,32 @@
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.zy.asrs.entity.LocMast">
        <id column="loc_no" property="locNo" />
        <result column="whs_type" property="whsType" />
        <result column="plt_type" property="pltType" />
        <result column="ctn_type" property="ctnType" />
        <result column="loc_sts" property="locSts" />
        <result column="sheet_no" property="sheetNo" />
        <result column="crn_no" property="crnNo" />
        <result column="row1" property="row1" />
        <result column="bay1" property="bay1" />
        <result column="lev1" property="lev1" />
        <result column="full_plt" property="fullPlt" />
        <result column="loc_type" property="locType" />
        <result column="loc_type1" property="locType1" />
        <result column="loc_type2" property="locType2" />
        <result column="loc_type3" property="locType3" />
        <result column="out_enable" property="outEnable" />
        <result column="io_time" property="ioTime" />
        <result column="first_time" property="firstTime" />
        <result column="modi_user" property="modiUser" />
        <result column="modi_time" property="modiTime" />
        <result column="appe_user" property="appeUser" />
        <result column="appe_time" property="appeTime" />
        <result column="error_time" property="errorTime" />
        <result column="error_memo" property="errorMemo" />
        <result column="ctn_kind" property="ctnKind" />
        <result column="sc_weight" property="scWeight" />
        <result column="inv_wh" property="invWh" />
        <result column="mk" property="mk" />
        <result column="barcode" property="barcode" />
        <result column="ctn_no" property="ctnNo" />
        <result column="qr_code_value" property="qrCodeValue" />
    </resultMap>
    <select id="queryFreeLocMast" resultMap="BaseResultMap">
        select top 1 *
        from asr_loc_mast
        where row1=#{row}
        and loc_sts='O'
        and row1 > 30
        <if test="locType1 != null">
            and loc_type1 = #{locType1}
        </if>
        order by loc_sts desc ,lev1 asc,bay1 asc
    </select>
    <select id="queryDemoSourceLoc" resultMap="BaseResultMap">
        select top 1 * from asr_loc_mast where crn_no = #{crnNo}
        and loc_sts='D'
        ORDER BY NEWID()
    </select>
    <select id="queryDemoLoc" resultMap="BaseResultMap">
        select top 1 * from asr_loc_mast where crn_no = #{crnNo} and loc_sts = 'O'
        ORDER BY NEWID()
    </select>
    <select id="queryByLoc" resultMap="BaseResultMap">
        select top 1 * from asr_loc_mast where loc_no = #{locNo}
        select * from asr_loc_mast where loc_no = #{locNo} limit 0,1
    </select>
    <select id="queryByQrCode" resultMap="BaseResultMap">
        select top 1 * from asr_loc_mast where qr_code_value = #{qrCodeValue}
        select * from asr_loc_mast where qr_code_value = #{qrCodeValue} limit 0,1
    </select>
    <select id="selectLocByLev" resultMap="BaseResultMap">
src/main/resources/mapper/WrkChargeMapper.xml
File was deleted
src/main/resources/mapper/WrkMastMapper.xml
@@ -5,79 +5,28 @@
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.zy.asrs.entity.WrkMast">
        <id column="wrk_no" property="wrkNo" />
        <result column="inv_wh" property="invWh" />
        <result column="ymd" property="ymd" />
        <result column="mk" property="mk" />
        <result column="whs_type" property="whsType" />
        <result column="wrk_sts" property="wrkSts" />
        <result column="io_type" property="ioType" />
        <result column="crn_no" property="crnNo" />
        <result column="ste_no" property="steNo" />
        <result column="out_most" property="outMost" />
        <result column="sheet_no" property="sheetNo" />
        <result column="io_pri" property="ioPri" />
        <result column="wrk_date" property="wrkDate" />
        <result column="loc_no" property="locNo" />
        <result column="sta_no" property="staNo" />
        <result column="source_sta_no" property="sourceStaNo" />
        <result column="source_loc_no" property="sourceLocNo" />
        <result column="loc_sts" property="locSts" />
        <result column="picking" property="picking" />
        <result column="link_mis" property="linkMis" />
        <result column="online_yn" property="onlineYn" />
        <result column="upd_mk" property="updMk" />
        <result column="exit_mk" property="exitMk" />
        <result column="plt_type" property="pltType" />
        <result column="empty_mk" property="emptyMk" />
        <result column="io_time" property="ioTime" />
        <result column="ctn_type" property="ctnType" />
        <result column="packed" property="packed" />
        <result column="ove_mk" property="oveMk" />
        <result column="mtn_type" property="mtnType" />
        <result column="user_no" property="userNo" />
        <result column="crn_str_time" property="crnStrTime" />
        <result column="crn_end_time" property="crnEndTime" />
        <result column="plc_str_time" property="plcStrTime" />
        <result column="crn_pos_time" property="crnPosTime" />
        <result column="load_time" property="loadTime" />
        <result column="exp_time" property="expTime" />
        <result column="ref_wrkno" property="refWrkno" />
        <result column="ref_iotime" property="refIotime" />
        <result column="modi_user" property="modiUser" />
        <result column="modi_time" property="modiTime" />
        <result column="appe_user" property="appeUser" />
        <result column="appe_time" property="appeTime" />
        <result column="pause_mk" property="pauseMk" />
        <result column="error_time" property="errorTime" />
        <result column="error_memo" property="errorMemo" />
        <result column="ctn_kind" property="ctnKind" />
        <result column="manu_type" property="manuType" />
        <result column="memo" property="memo" />
        <result column="sc_weight" property="scWeight" />
        <result column="log_mk" property="logMk" />
        <result column="log_err_time" property="logErrTime" />
        <result column="log_err_memo" property="logErrMemo" />
        <result column="barcode" property="barcode" />
        <result column="Pdc_type" property="pdcType" />
        <result column="ctn_no" property="ctnNo" />
        <result column="full_plt" property="fullPlt" />
        <result column="shuttle_no" property="shuttleNo" />
        <result column="lift_no" property="liftNo" />
    </resultMap>
    <select id="selectToBeCompleteData" resultMap="BaseResultMap">
        select * from asr_wrk_mast where ((wrk_sts = 4 Or wrk_sts = 14 ) and io_type != 103 and io_type != 104 and io_type != 107 ) or (wrk_sts = 2 and io_type=6) order by upd_mk,io_time,wrk_no
    </select>
    <select id="selectToBeHistoryData" resultMap="BaseResultMap">
        select * from asr_wrk_mast
        where wrk_sts=5
        or (wrk_sts=15 and ove_mk='Y' and wrk_no not in (select wrk_no from asr_bas_devp))
        or (wrk_sts=15 and dateadd(mi,15,crn_end_time) &lt;= getdate() and wrk_no not in (select wrk_no from asr_bas_devp))
        or (wrk_sts=15 and crn_end_time is null and wrk_no not in (select wrk_no from asr_bas_devp))
        order by io_time,wrk_no asc
    </select>
    <select id="selectPakInStep1" resultMap="BaseResultMap">
        select * from asr_wrk_mast where source_sta_no=#{sourceStaNo} and wrk_sts=2 and barcode=#{barcode} and (io_type=1 or io_type=10) order by io_pri desc,io_time,wrk_no ASC limit 0,1
@@ -105,20 +54,20 @@
    <select id="selectLiftStep223103" resultMap="BaseResultMap">
        select * from asr_wrk_mast
        where 1=1
        and wrk_sts in (2,23,103)
        and wrk_sts in (2,103,303)
        order by io_pri desc,wrk_sts desc
    </select>
    <select id="selectByWorkNo324104" resultMap="BaseResultMap">
        select * from asr_wrk_mast
        where wrk_no=#{workNo}
        and wrk_sts in (3,24,103,106)
        and wrk_sts in (3,104,303,306)
        limit 0,1
    </select>
    <select id="selectBy2125" resultMap="BaseResultMap">
        select * from asr_wrk_mast
        where wrk_sts in (21,25)
        where wrk_sts in (101,105)
        and io_type in (101,103,107,110)
        order by io_pri desc,wrk_sts desc
    </select>
@@ -126,7 +75,7 @@
    <select id="selectNoShuttleWrkByLev" resultMap="BaseResultMap">
        select * from asr_wrk_mast
        where shuttle_no is null
        and ((wrk_sts = 2 and loc_no like #{lev}) or (wrk_sts = 21 and source_loc_no like #{lev}))
        and ((wrk_sts = 2 and loc_no like #{lev}) or (wrk_sts = 101 and source_loc_no like #{lev}))
        order by io_pri desc,wrk_sts desc
    </select>
@@ -140,62 +89,67 @@
    <select id="selectShuttleOutWrkByLev" resultMap="BaseResultMap">
        select * from asr_wrk_mast
        where shuttle_no is not null
        and (wrk_sts not in (29,30) and source_loc_no like #{lev})
        and (wrk_sts not in (109,110) and source_loc_no like #{lev})
        order by io_pri desc,wrk_sts desc
    </select>
    <select id="selectLiftWrkMast" resultMap="BaseResultMap">
        select top 1 * from asr_wrk_mast
        select * from asr_wrk_mast
        where lift_no = #{liftNo}
        and wrk_sts in (3,4,24,25,102,103,104,105,106,107,108,109)
        and wrk_sts in (3,4,104,105,302,303,304,305,306,307,308,309)
        limit 0,1
    </select>
    <select id="selectLocToLocWrkMast" resultMap="BaseResultMap">
        select * from asr_wrk_mast
        where io_type in (11)
        and wrk_sts not in (9,10,29,30)
        and wrk_sts not in (9,10,109,110)
        order by io_pri desc,wrk_sts desc
    </select>
    <select id="selectPickStepByBarcode" resultMap="BaseResultMap">
        select top 1 * from asr_wrk_mast
        select * from asr_wrk_mast
        where io_type in (53,103,107)
        and wrk_sts in (2,3,34,29)
        and wrk_sts in (2,3,104,109)
        and barcode = #{barcode}
        order by io_pri desc,wrk_sts desc
        limit 0,1
    </select>
    <select id="selectShuttleHasMoveWorking" resultMap="BaseResultMap">
        select top 1 * from asr_wrk_mast
        select * from asr_wrk_mast
        where 1=1
        and shuttle_no = #{shuttleNo}
        and wrk_sts not in (111)
        and wrk_sts not in (311)
        and io_type = 200
        order by io_pri desc,io_time,wrk_no asc
        limit 0,1
    </select>
    <select id="selectShuttleMoveWrk" resultMap="BaseResultMap">
        select * from asr_wrk_mast
        where 1=1
        and wrk_sts in (101,103,105,107,109,111)
        and wrk_sts in (301,302,303,304,305,306,307,308,309,310,311)
        and io_type = 200
        order by io_pri desc,io_time,wrk_no asc
    </select>
    <select id="selectShuttleWorking" resultMap="BaseResultMap">
        select top 1 * from asr_wrk_mast
        select * from asr_wrk_mast
        where 1=1
        and shuttle_no = #{shuttleNo}
        and wrk_sts not in (9,10,23,29,30)
        and wrk_sts not in (9,10,109,110,210)
        and io_type not in (200)
        order by io_pri desc,io_time,wrk_no asc
        limit 0,1
    </select>
    <select id="selectByBarcode" resultMap="BaseResultMap">
        select top 1 * from asr_wrk_mast
        select * from asr_wrk_mast
        where 1=1
        and barcode = #{barcode}
        order by io_pri desc,io_time,wrk_no asc
        limit 0,1
    </select>
    <select id="selectInWrkMastByLiftNo" resultMap="BaseResultMap">
@@ -207,4 +161,11 @@
        order by io_pri desc,io_time,wrk_no asc
    </select>
    <select id="selectChargeWorking" resultMap="BaseResultMap">
        select * from asr_wrk_mast
        where wrk_sts in (201,202,203)
        and shuttle_no = #{shuttleNo}
        order by priority desc,start_time,wrk_no asc
    </select>
</mapper>