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.mapper.WrkMastMapper;
|
import com.zy.asrs.service.BasLiftOptService;
|
import com.zy.asrs.service.BasLiftService;
|
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.ArrayList;
|
import java.util.Date;
|
import java.util.HashMap;
|
import java.util.List;
|
|
/**
|
* 提升机线程
|
*/
|
@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.setModel(liftProtocol.getModel());
|
basLift.setBusy(liftProtocol.getBusy());
|
basLift.setFrontOverrun(liftProtocol.getFrontOverrun());
|
basLift.setBackOverrun(liftProtocol.getBackOverrun());
|
basLift.setLeftOverrun(liftProtocol.getLeftOverrun());
|
basLift.setRightOverrun(liftProtocol.getRightOverrun());
|
basLift.setOverHeight(liftProtocol.getOverHeight());
|
basLift.setOverWeight(liftProtocol.getOverWeight());
|
basLift.setHasTray(liftProtocol.getHasTray());
|
basLift.setHasCar(liftProtocol.getHasCar());
|
basLift.setDeviceError(liftProtocol.getDeviceError());
|
basLift.setDistAddress(liftProtocol.getDistAddress().intValue());
|
basLift.setCompleteTaskNo(liftProtocol.getCompleteTaskNo().intValue());
|
basLift.setLev(liftProtocol.getLev().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()));
|
}
|
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));//错误码
|
}
|
|
} 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;
|
}
|
|
WrkMastMapper wrkMastMapper = SpringUtils.getBean(WrkMastMapper.class);
|
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();
|
|
//取出命令
|
NyLiftCommand command = commands.get(commandStep);
|
|
if (!redisCommand.getLiftNo().equals(liftProtocol.getLiftNo())) {
|
return false;
|
}
|
|
//下发命令
|
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);
|
}
|
|
//判断数据是否执行完成
|
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);
|
|
}
|
|
}
|