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.Cools;
|
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.BasShuttle;
|
import com.zy.asrs.entity.BasShuttleOpt;
|
import com.zy.asrs.service.BasLiftOptService;
|
import com.zy.asrs.service.BasLiftService;
|
import com.zy.asrs.service.BasShuttleOptService;
|
import com.zy.asrs.service.BasShuttleService;
|
import com.zy.common.utils.CommonUtils;
|
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.LiftAssignCommand;
|
import com.zy.core.model.command.LiftCommand;
|
import com.zy.core.model.command.ShuttleAssignCommand;
|
import com.zy.core.model.command.ShuttleCommand;
|
import com.zy.core.model.protocol.LiftProtocol;
|
import lombok.Data;
|
import lombok.extern.slf4j.Slf4j;
|
|
import java.text.MessageFormat;
|
import java.util.ArrayList;
|
import java.util.Date;
|
import java.util.HashMap;
|
import java.util.List;
|
|
/**
|
* 提升机线程
|
*/
|
@Data
|
@Slf4j
|
public class LiftThread implements Runnable, ThreadHandler {
|
|
private ModbusTcpNet modbusTcpNet;
|
private LiftSlave slave;
|
private LiftProtocol liftProtocol;
|
private RedisUtil redisUtil;
|
|
public LiftThread(LiftSlave slave,RedisUtil redisUtil) {
|
this.slave = slave;
|
this.redisUtil = redisUtil;
|
}
|
|
@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:
|
readStatus();
|
break;
|
// 写入数据
|
case 2:
|
write((LiftCommand) task.getData());
|
break;
|
//分配任务
|
case 3:
|
assignWork((LiftAssignCommand) task.getData());
|
break;
|
default:
|
break;
|
}
|
Thread.sleep(500);
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
}
|
}
|
|
@Override
|
public boolean connect() {
|
boolean result = false;
|
//-------------------------提升机连接方法------------------------//
|
modbusTcpNet = new ModbusTcpNet(slave.getIp(), slave.getPort(), (byte) 0x02);
|
// 当你需要指定格式的数据解析时,就需要设置下面的这个信息
|
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;
|
}
|
|
@Override
|
public void close() {
|
modbusTcpNet.ConnectClose();
|
}
|
|
private void readStatus() {
|
try {
|
OperateResultExOne<byte[]> result = modbusTcpNet.Read("29", (short) 50);
|
if (result.IsSuccess) {
|
if (null == liftProtocol) {
|
liftProtocol = new LiftProtocol();
|
liftProtocol.setLiftNo(slave.getId().shortValue());
|
}
|
|
//----------读取提升机状态-----------
|
//获取数据
|
byte[] content = result.Content;
|
//提升机锁定
|
liftProtocol.setLiftLock(CommonUtils.shortToBoolean(modbusTcpNet.getByteTransform().TransInt16(content, 0)));
|
//位置到达反馈
|
liftProtocol.setPositionArrivalFeedback(modbusTcpNet.getByteTransform().TransInt16(content,2));
|
//准备就绪
|
liftProtocol.setReady(CommonUtils.shortToBoolean(modbusTcpNet.getByteTransform().TransInt16(content,4)));
|
//运行中
|
liftProtocol.setRunning(CommonUtils.shortToBoolean(modbusTcpNet.getByteTransform().TransInt16(content,6)));
|
//联机/单机
|
liftProtocol.setMode(CommonUtils.shortToBoolean(modbusTcpNet.getByteTransform().TransInt16(content,8)));
|
|
//以下参数并未进行调整(需要后续针对实机进行获取和调试)
|
//输送线前端光电有货
|
liftProtocol.setLineFrontHasStock(modbusTcpNet.getByteTransform().TransBool(content,10));
|
//输送线正转反馈
|
liftProtocol.setForwardRotationFeedback(modbusTcpNet.getByteTransform().TransBool(content,12));
|
//输送线反转反馈
|
liftProtocol.setReverseFeedback(modbusTcpNet.getByteTransform().TransBool(content,14));
|
//输送线电机过载
|
liftProtocol.setMotorOverload(modbusTcpNet.getByteTransform().TransBool(content,16));
|
//输送线末端光电有货
|
liftProtocol.setLineEndHasStock(modbusTcpNet.getByteTransform().TransBool(content,18));
|
//进输送线卡托盘报警
|
liftProtocol.setInConveyLineCardTrayAlarm(modbusTcpNet.getByteTransform().TransBool(content,20));
|
//出输送线卡托盘报警
|
liftProtocol.setOutConveyLineCardTrayAlarm(modbusTcpNet.getByteTransform().TransBool(content,22));
|
//平台位置偏差报警
|
liftProtocol.setPlatPositionDeviationAlarm(modbusTcpNet.getByteTransform().TransBool(content,24));
|
//平台扭矩偏差报警
|
liftProtocol.setPlatTorqueDeviationAlarm(modbusTcpNet.getByteTransform().TransBool(content,26));
|
//平台四向车检测
|
liftProtocol.setPlatShuttleCheck(modbusTcpNet.getByteTransform().TransBool(content,28));
|
//未就绪状态
|
liftProtocol.setNotReady(modbusTcpNet.getByteTransform().TransInt16(content,30));
|
//伺服1错误
|
liftProtocol.setServoError1(modbusTcpNet.getByteTransform().TransInt16(content,32));
|
//伺服2错误
|
liftProtocol.setServoError2(modbusTcpNet.getByteTransform().TransInt16(content,34));
|
//伺服3错误
|
liftProtocol.setServoError3(modbusTcpNet.getByteTransform().TransInt16(content,36));
|
//伺服4错误
|
liftProtocol.setServoError4(modbusTcpNet.getByteTransform().TransInt16(content,38));
|
//提升机实际速度反馈
|
liftProtocol.setLiftActualSpeed(modbusTcpNet.getByteTransform().TransInt16(content,40));
|
|
///读取提升机状态-end
|
|
//小车处于运行状态,将标记置为true
|
if (liftProtocol.getRunning()) {
|
liftProtocol.setPakMk(true);
|
}
|
|
//提升机处于锁定、未运行、就绪、标记true、有任务号
|
if (liftProtocol.getLiftLock()
|
&& !liftProtocol.getRunning()
|
&& liftProtocol.getReady()
|
&& liftProtocol.getPakMk()
|
&& liftProtocol.getTaskNo() != 0
|
&& liftProtocol.getAssignCommand() != null) {
|
//还有未完成的命令
|
executeWork(liftProtocol.getAssignCommand());
|
}
|
|
//将提升机状态保存至数据库
|
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.setLiftLock(liftProtocol.getLiftLock());
|
basLift.setPositionArrivalFeedback(liftProtocol.getPositionArrivalFeedback().intValue());
|
basLift.setReady(liftProtocol.getReady());
|
basLift.setRunning(liftProtocol.getRunning());
|
basLift.setMode(liftProtocol.getMode());
|
basLift.setLineFrontHasStock(liftProtocol.getLineFrontHasStock());
|
basLift.setForwardRotationFeedback(liftProtocol.getForwardRotationFeedback());
|
basLift.setReverseFeedback(liftProtocol.getReverseFeedback());
|
basLift.setMotorOverload(liftProtocol.getMotorOverload());
|
basLift.setLineEndHasStock(liftProtocol.getLineEndHasStock());
|
basLift.setInConveyLineCardTrayAlarm(liftProtocol.getInConveyLineCardTrayAlarm());
|
basLift.setOutConveyLineCardTrayAlarm(liftProtocol.getOutConveyLineCardTrayAlarm());
|
basLift.setPlatPositionDeviationAlarm(liftProtocol.getPlatPositionDeviationAlarm());
|
basLift.setPlatTorqueDeviationAlarm(liftProtocol.getPlatTorqueDeviationAlarm());
|
basLift.setPlatShuttleCheck(liftProtocol.getPlatShuttleCheck());
|
basLift.setNotReady(liftProtocol.getNotReady().intValue());
|
basLift.setServoError1(liftProtocol.getServoError1().intValue());
|
basLift.setServoError2(liftProtocol.getServoError2().intValue());
|
basLift.setServoError3(liftProtocol.getServoError3().intValue());
|
basLift.setServoError4(liftProtocol.getServoError4().intValue());
|
basLift.setLiftActualSpeed(liftProtocol.getLiftActualSpeed().intValue());
|
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()));
|
}
|
} 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()));
|
initLift();
|
}
|
}
|
|
private boolean write(LiftCommand command){
|
if (null == command) {
|
News.error("提升机写入命令为空");
|
return false;
|
}
|
|
command.setLiftNo(slave.getId().shortValue());
|
// 开始任务
|
short[] array = new short[30];
|
//开始运行
|
array[0] = command.getRun();
|
if (command.getDistPosition() != null) {
|
//目标位置
|
array[1] = command.getDistPosition();
|
}
|
if (command.getSpeed() != null) {
|
//运行速度
|
array[2] = command.getSpeed();
|
}
|
if (command.getHeight2() != null) {
|
//二层高度设定
|
array[3] = command.getHeight2();
|
}
|
if (command.getHeight3() != null) {
|
//三层高度设定
|
array[4] = command.getHeight3();
|
}
|
if (command.getHeight4() != null) {
|
//四层高度设定
|
array[5] = command.getHeight4();
|
}
|
if (command.getLiftLockShortValue() != null) {
|
//提升机锁定
|
array[29] = command.getLiftLockShortValue();
|
}
|
|
OperateResult result = modbusTcpNet.Write("0", array);;
|
if (result != null && result.IsSuccess) {
|
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 void assignWork(LiftAssignCommand assignCommand) {
|
//将此map存入redis中
|
HashMap<String, Object> map = new HashMap<>();
|
|
//手动模式指令
|
if (!assignCommand.getAuto()) {
|
LiftCommand command = new LiftCommand();
|
//提升机当前楼层
|
Short lev = liftProtocol.getLev();
|
List<LiftCommand> commands = assignCommand.getCommands();
|
if (commands == null) {
|
commands = new ArrayList<LiftCommand>();
|
}
|
liftProtocol.setTaskNo(assignCommand.getTaskNo());
|
switch (assignCommand.getTaskMode()) {
|
case 1://上升一层
|
command.setRun((short) 1);//升降
|
command.setDistPosition(++lev);
|
break;
|
case 2://下降一层
|
command.setRun((short) 1);//下降
|
command.setDistPosition(--lev);
|
break;
|
case 3://有货正转
|
command.setRun((short) 6);
|
break;
|
case 4://有货反转
|
command.setRun((short) 3);
|
break;
|
case 5://复位
|
command.setRun((short) 0);
|
command.setLiftLock(false);
|
break;
|
default:
|
}
|
commands.add(command);
|
assignCommand.setCommands(commands);
|
}
|
|
//提升机号
|
map.put("lift_no", assignCommand.getLiftNo());
|
//工作号
|
map.put("wrk_no", assignCommand.getTaskNo());
|
//命令执行步序
|
map.put("commandStep", 0);
|
//命令
|
map.put("assignCommand", assignCommand);
|
//任务数据保存到redis
|
redisUtil.set("lift_wrk_no_" + assignCommand.getTaskNo(), JSON.toJSONString(map));
|
liftProtocol.setAssignCommand(assignCommand);
|
liftProtocol.setProtocolStatus(LiftProtocolStatusType.WORKING);
|
//执行下发任务
|
executeWork(assignCommand);
|
}
|
|
//执行任务
|
private boolean executeWork(LiftAssignCommand assignCommand) {
|
//读取redis数据
|
if (assignCommand == null) {
|
return false;
|
}
|
|
//将标记置为false(防止重发)
|
liftProtocol.setPakMk(false);
|
|
Object o = redisUtil.get("lift_wrk_no_" + assignCommand.getTaskNo());
|
if (o == null) {
|
return false;
|
}
|
HashMap map = JSON.parseObject(o.toString(), HashMap.class);
|
List<LiftCommand> commands = assignCommand.getCommands();
|
//当前步序
|
int commandStep = Integer.parseInt(map.get("commandStep").toString());
|
//总步序
|
int size = commands.size();
|
|
//取出命令
|
LiftCommand command = commands.get(commandStep);
|
//下发命令
|
if (!write(command)) {
|
News.error("提升机命令下发失败,提升机号={},任务数据={}", command.getLiftNo(), JSON.toJSON(command));
|
return false;
|
}else {
|
News.info("提升机命令下发成功,提升机号={},任务数据={}", command.getLiftNo(), JSON.toJSON(command));
|
|
//判断数据是否执行完成
|
if (commandStep < size - 1) {
|
//更新redis数据
|
//步序增加
|
commandStep++;
|
map.put("commandStep", commandStep);
|
//任务数据保存到redis
|
redisUtil.set("lift_wrk_no_" + map.get("wrk_no").toString(), JSON.toJSONString(map));
|
}else {
|
//已执行完成
|
//保存数据到数据库做流水
|
BasLiftOptService liftOptService = SpringUtils.getBean(BasLiftOptService.class);
|
if (liftOptService != null) {
|
BasLiftOpt opt = new BasLiftOpt(
|
assignCommand.getTaskNo().intValue(),
|
assignCommand.getLiftNo().intValue(),
|
new Date(),
|
null,
|
null,
|
null,
|
JSON.toJSONString(assignCommand)
|
);
|
liftOptService.insert(opt);
|
}
|
//删除redis
|
redisUtil.del("lift_wrk_no_" + map.get("wrk_no").toString());
|
|
if (assignCommand.getAuto()) {
|
//对主线程抛出等待确认状态waiting
|
liftProtocol.setProtocolStatus(LiftProtocolStatusType.WAITING);
|
News.info("提升机任务执行完成等待确认中,提升机号={},任务数据={}", command.getLiftNo(), JSON.toJSON(command));
|
}else {
|
//手动模式不抛出等待状态
|
if (assignCommand.getTaskMode() == 5) {
|
liftProtocol.setTaskNo((short) 0);
|
liftProtocol.setShuttleNo((short) 0);
|
liftProtocol.setProtocolStatus(LiftProtocolStatusType.IDLE);
|
liftProtocol.setPakMk(true);
|
}
|
News.info("提升机手动任务执行完成,提升机号={},任务数据={}", command.getLiftNo(), JSON.toJSON(command));
|
}
|
|
//下发一条提升机解锁命令
|
LiftCommand liftCommand = new LiftCommand();
|
liftCommand.setRun((short) 0);
|
liftCommand.setLiftNo(command.getLiftNo());
|
liftCommand.setLiftLock(false);
|
if (write(liftCommand)) {
|
News.info("提升机状态已解锁,提升机号={},任务数据={}", command.getLiftNo(), JSON.toJSON(command));
|
}
|
|
}
|
}
|
|
return true;
|
}
|
|
/**
|
* 初始化提升机
|
*/
|
private void initLift() {
|
if (null == liftProtocol) {
|
liftProtocol = new LiftProtocol();
|
}
|
}
|
|
/******************************************************************************************/
|
/**************************************** 测试专用 *****************************************/
|
/*****************************************************************************************/
|
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);
|
|
}
|
|
}
|