package com.zy.core.network.real;
|
|
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.alibaba.fastjson.JSONObject;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.core.common.DateUtils;
|
import com.core.common.SpringUtils;
|
import com.zy.asrs.entity.BasDevp;
|
import com.zy.asrs.entity.DeviceConfig;
|
import com.zy.asrs.service.BasDevpService;
|
import com.zy.common.utils.RedisUtil;
|
import com.zy.core.News;
|
import com.zy.core.cache.OutputQueue;
|
import com.zy.core.model.CommandResponse;
|
import com.zy.core.model.StationObjModel;
|
import com.zy.core.model.command.StationCommand;
|
import com.zy.core.network.api.ZyStationConnectApi;
|
import com.zy.core.network.entity.ZyStationStatusEntity;
|
import lombok.extern.slf4j.Slf4j;
|
|
import java.text.MessageFormat;
|
import java.util.Collections;
|
import java.util.Comparator;
|
import java.util.Date;
|
import java.util.List;
|
|
/**
|
* 输送站真实连接(PLC)
|
*/
|
@Slf4j
|
public class ZyStationV4RealConnect implements ZyStationConnectApi {
|
|
private static final int TASK_AREA_LENGTH = 48;
|
private static final int TASK_AREA_SLOT_SIZE = 12;
|
private static final int TASK_AREA_SLOT_COUNT = 3;
|
|
private List<ZyStationStatusEntity> statusList;
|
private List<StationObjModel> barcodeOriginList;
|
private SiemensS7Net siemensNet;
|
private DeviceConfig deviceConfig;
|
private RedisUtil redisUtil;
|
|
public ZyStationV4RealConnect(DeviceConfig deviceConfig, RedisUtil redisUtil) {
|
this.deviceConfig = deviceConfig;
|
this.redisUtil = redisUtil;
|
}
|
|
@Override
|
public boolean connect() {
|
boolean connected = false;
|
siemensNet = new SiemensS7Net(SiemensPLCS.S1200, deviceConfig.getIp());
|
OperateResult connect = siemensNet.ConnectServer();
|
if (connect.IsSuccess) {
|
connected = true;
|
OutputQueue.DEVP.offer(MessageFormat.format("【{0}】输送站plc连接成功 ===>> [id:{1}] [ip:{2}] [port:{3}]",
|
DateUtils.convert(new Date()), deviceConfig.getDeviceNo(), deviceConfig.getIp(),
|
deviceConfig.getPort()));
|
News.info("输送站plc连接成功 ===>> [id:{}] [ip:{}] [port:{}]",
|
deviceConfig.getDeviceNo(), deviceConfig.getIp(), deviceConfig.getPort());
|
} else {
|
OutputQueue.DEVP.offer(MessageFormat.format("【{0}】输送站plc连接失败!!! ===>> [id:{1}] [ip:{2}] [port:{3}]",
|
DateUtils.convert(new Date()), deviceConfig.getDeviceNo(), deviceConfig.getIp(),
|
deviceConfig.getPort()));
|
News.error("输送站plc连接失败!!! ===>> [id:{}] [ip:{}] [port:{}]",
|
deviceConfig.getDeviceNo(), deviceConfig.getIp(), deviceConfig.getPort());
|
}
|
// siemensNet.ConnectClose();
|
return connected;
|
}
|
|
@Override
|
public boolean disconnect() {
|
siemensNet.ConnectClose();
|
return true;
|
}
|
|
@Override
|
public List<ZyStationStatusEntity> getStatus(Integer deviceNo) {
|
if (statusList == null) {
|
BasDevpService basDevpService = SpringUtils.getBean(BasDevpService.class);
|
if (basDevpService == null) {
|
return Collections.emptyList();
|
}
|
|
BasDevp basDevp = basDevpService
|
.getOne(new QueryWrapper<BasDevp>().eq("devp_no", deviceConfig.getDeviceNo()));
|
if (basDevp == null) {
|
return Collections.emptyList();
|
}
|
|
statusList = JSONObject.parseArray(basDevp.getStationList(), ZyStationStatusEntity.class);
|
if (statusList != null) {
|
statusList.sort(Comparator.comparing(ZyStationStatusEntity::getStationId));
|
}
|
barcodeOriginList = basDevp.getBarcodeStationList$();
|
}
|
|
if (siemensNet == null) {
|
return statusList;
|
}
|
|
OperateResultExOne<byte[]> result = siemensNet.Read("DB100.0", (short) (statusList.size() * 10));
|
if (result.IsSuccess) {
|
for (int i = 0; i < statusList.size(); i++) {
|
ZyStationStatusEntity statusEntity = statusList.get(i); // 站点编号
|
statusEntity.setTaskNo(siemensNet.getByteTransform().TransInt32(result.Content, i * 10)); // 工作号
|
statusEntity.setTargetStaNo((int) siemensNet.getByteTransform().TransInt16(result.Content, i * 10 + 4)); // 目标站
|
|
boolean[] status = siemensNet.getByteTransform().TransBool(result.Content, i * 10 + 6, 1);
|
statusEntity.setAutoing(status[0]); // 自动
|
statusEntity.setLoading(status[1]); // 有物
|
statusEntity.setInEnable(status[2]); // 可入
|
statusEntity.setOutEnable(status[3]);// 可出
|
statusEntity.setEmptyMk(status[4]); // 空托盘
|
statusEntity.setFullPlt(status[5]); // 满托盘
|
|
boolean[] status2 = siemensNet.getByteTransform().TransBool(result.Content, i * 10 + 7, 1);
|
statusEntity.setEnableIn(status2[1]);//启动入库
|
statusEntity.setRunBlock(status2[2]);//重新规划路线
|
|
Integer palletHeight = null;
|
if (status[7]) {
|
palletHeight = 1;//低
|
}
|
if (status2[0]) {
|
palletHeight = 2;//中
|
}
|
if (status[6]) {
|
palletHeight = 3;//高
|
}
|
statusEntity.setPalletHeight(palletHeight);//高低信号
|
|
statusEntity.setError(0);//默认无报警
|
|
statusEntity.setTaskWriteIdx((int) siemensNet.getByteTransform().TransInt16(result.Content, i * 10 + 8));//任务可写区
|
}
|
}
|
|
// 条码扫描器
|
OperateResultExOne<byte[]> result2 = siemensNet.Read("DB101.16", (short) (barcodeOriginList.size() * 16));
|
if (result2.IsSuccess) {
|
for (int i = 0; i < barcodeOriginList.size(); i++) {
|
ZyStationStatusEntity barcodeEntity = findStatusEntityByBarcodeIdx(i + 1);
|
if (barcodeEntity == null) {
|
continue;
|
}
|
String barcode = siemensNet.getByteTransform().TransString(result2.Content, i * 16 + 2, 14, "UTF-8");
|
barcode = barcode.trim();
|
barcodeEntity.setBarcode(barcode);
|
}
|
}
|
|
// 称重
|
OperateResultExOne<byte[]> result3 = siemensNet.Read("DB102.4", (short) (barcodeOriginList.size() * 4));
|
if (result3.IsSuccess) {
|
for (int i = 0; i < barcodeOriginList.size(); i++) {
|
ZyStationStatusEntity barcodeEntity = findStatusEntityByBarcodeIdx(i + 1);
|
if (barcodeEntity == null) {
|
continue;
|
}
|
double weight = (double) siemensNet.getByteTransform().TransSingle(result3.Content, i * 4);
|
barcodeEntity.setWeight(weight);
|
}
|
}
|
|
// 报警信息
|
OperateResultExOne<byte[]> result4 = siemensNet.Read("DB103.2", (short) (barcodeOriginList.size() * 2));
|
if (result4.IsSuccess) {
|
for (int i = 0; i < barcodeOriginList.size(); i++) {
|
ZyStationStatusEntity barcodeEntity = findStatusEntityByBarcodeIdx(i + 1);
|
if (barcodeEntity == null) {
|
continue;
|
}
|
|
StringBuilder sb = new StringBuilder();
|
boolean[] status1 = siemensNet.getByteTransform().TransBool(result4.Content, i * 2, 1);
|
boolean[] status2 = siemensNet.getByteTransform().TransBool(result4.Content, i * 2 + 1, 1);
|
|
if(status1[0]){
|
sb.append("左超宽报警;");
|
}
|
if(status1[1]) {
|
sb.append("右超宽报警;");
|
}
|
if(status1[2]) {
|
sb.append("前超长报警;");
|
}
|
if(status1[3]) {
|
sb.append("后超长报警;");
|
}
|
if(status1[4]) {
|
sb.append("超高报警;");
|
}
|
if(status1[5]) {
|
sb.append("有货报警,空托入库时检测托盘上有无货物;");
|
}
|
if(status1[6]) {
|
sb.append("重量异常报警;");
|
}
|
if(status1[7]) {
|
sb.append("扫码异常;");
|
}
|
|
if(sb.length() > 0) {
|
barcodeEntity.setError(1);
|
}else {
|
barcodeEntity.setError(0);
|
}
|
barcodeEntity.setErrorMsg(sb.toString());
|
}
|
}
|
|
return statusList;
|
}
|
|
@Override
|
public CommandResponse sendCommand(Integer deviceNo, StationCommand command) {
|
CommandResponse commandResponse = new CommandResponse(false);
|
if (null == command) {
|
commandResponse.setMessage("命令为空");
|
return commandResponse;
|
}
|
|
getStatus(deviceNo);
|
|
int stationIdx = findIndex(command.getStationId());
|
if (stationIdx == -1) {
|
commandResponse.setMessage("命令下发失败,未找到站点状态");
|
return commandResponse;
|
}
|
|
ZyStationStatusEntity statusEntity = statusList.get(stationIdx);
|
Integer taskWriteIdx = statusEntity == null ? null : statusEntity.getTaskWriteIdx();
|
if (taskWriteIdx == null || taskWriteIdx <= 0) {
|
commandResponse.setMessage("命令下发失败,当前无可用任务写入区");
|
return commandResponse;
|
}
|
|
if (isDuplicateStationCommand(statusEntity, command)) {
|
log.info("输送线命令重复,已跳过当前站点命令。任务号={},站点号={},目标站={}",
|
command.getTaskNo(), command.getStationId(), command.getTargetStaNo());
|
commandResponse.setResult(true);
|
commandResponse.setMessage("命令重复,已跳过下发");
|
return commandResponse;
|
}
|
|
if (existsDuplicateTaskAreaCommand(stationIdx, command)) {
|
log.info("输送线命令重复,已跳过任务写入区重复命令。任务号={},站点号={},目标站={}",
|
command.getTaskNo(), command.getStationId(), command.getTargetStaNo());
|
commandResponse.setResult(true);
|
commandResponse.setMessage("任务区已有相同命令,已跳过下发");
|
return commandResponse;
|
}
|
|
int useTaskWriteIdx = getTaskWriteIdx(stationIdx, taskWriteIdx);
|
if (useTaskWriteIdx == -1) {
|
commandResponse.setMessage("命令下发超时,无法找到可用下发区域");
|
return commandResponse;
|
}
|
|
OperateResult writeTaskNo = siemensNet.Write("DB13." + (stationIdx * TASK_AREA_LENGTH + (useTaskWriteIdx * TASK_AREA_SLOT_SIZE)), command.getTaskNo());
|
if (!writeTaskNo.IsSuccess) {
|
log.error("写入输送线命令失败。站点编号={},站点数据={}", command.getTaskNo(), JSON.toJSON(command));
|
commandResponse.setResult(false);
|
commandResponse.setMessage("命令下发失败,写入工作号失败");
|
return commandResponse;
|
}
|
|
OperateResult writeData = siemensNet.Write("DB13." + (stationIdx * TASK_AREA_LENGTH + (useTaskWriteIdx * TASK_AREA_SLOT_SIZE + 4)), command.getTargetStaNo().shortValue());
|
if (!writeData.IsSuccess) {
|
log.error("写入输送线命令失败。站点编号={},站点数据={}", command.getTaskNo(), JSON.toJSON(command));
|
commandResponse.setResult(false);
|
commandResponse.setMessage("命令下发失败,写入数据区域失败");
|
return commandResponse;
|
}
|
|
log.info("写入输送线命令成功。任务号={},站点数据={}", command.getTaskNo(), JSON.toJSON(command));
|
commandResponse.setResult(true);
|
return commandResponse;
|
}
|
|
@Override
|
public synchronized CommandResponse sendOriginCommand(String address, short[] data) {
|
CommandResponse commandResponse = new CommandResponse(false);
|
if (null == data || data.length == 0) {
|
commandResponse.setMessage("数据为空");
|
return commandResponse;
|
}
|
|
OperateResult write = siemensNet.Write(address, data);
|
if (write.IsSuccess) {
|
log.info("写入原始命令成功。地址={},数据={}", address, JSON.toJSON(data));
|
commandResponse.setResult(true);
|
} else {
|
log.error("写入原始命令失败。地址={},数据={}", address, JSON.toJSON(data));
|
commandResponse.setResult(false);
|
}
|
return commandResponse;
|
}
|
|
@Override
|
public byte[] readOriginCommand(String address, int length) {
|
OperateResultExOne<byte[]> result = siemensNet.Read(address, (short) length);
|
if (result.IsSuccess) {
|
return result.Content;
|
}
|
return new byte[0];
|
}
|
|
private ZyStationStatusEntity findStatusEntityByBarcodeIdx(Integer barcodeIdx) {
|
Integer stationId = null;
|
for (StationObjModel stationObjModel : barcodeOriginList) {
|
if (stationObjModel.getBarcodeIdx().equals(barcodeIdx)) {
|
stationId = stationObjModel.getStationId();
|
break;
|
}
|
}
|
|
for (ZyStationStatusEntity zyStationStatusEntity : statusList) {
|
if(zyStationStatusEntity.getStationId().equals(stationId)) {
|
return zyStationStatusEntity;
|
}
|
}
|
return null;
|
}
|
|
private int getTaskWriteIdx(int stationIdx, Integer taskWriteIdx) {
|
int useIdx = -1;
|
if (stationIdx < 0 || taskWriteIdx == null || taskWriteIdx <= 0) {
|
return useIdx;
|
}
|
OperateResultExOne<byte[]> resultTask = siemensNet.Read("DB13." + (stationIdx * TASK_AREA_LENGTH), (short) TASK_AREA_LENGTH);
|
if (resultTask.IsSuccess) {
|
int taskNo = siemensNet.getByteTransform().TransInt32(resultTask.Content, taskWriteIdx * TASK_AREA_SLOT_SIZE);
|
int startPoint = siemensNet.getByteTransform().TransInt16(resultTask.Content, taskWriteIdx * TASK_AREA_SLOT_SIZE + 4);
|
int targetPoint = siemensNet.getByteTransform().TransInt16(resultTask.Content, taskWriteIdx * TASK_AREA_SLOT_SIZE + 6);
|
if (taskNo == 0 && startPoint == 0 && targetPoint == 0) {
|
useIdx = taskWriteIdx;
|
}
|
}
|
return useIdx;
|
}
|
|
private boolean isDuplicateStationCommand(ZyStationStatusEntity statusEntity, StationCommand command) {
|
if (statusEntity == null || command == null) {
|
return false;
|
}
|
return command.getTaskNo() != null
|
&& command.getTargetStaNo() != null
|
&& command.getTaskNo().equals(statusEntity.getTaskNo())
|
&& command.getTargetStaNo().equals(statusEntity.getTargetStaNo());
|
}
|
|
private boolean existsDuplicateTaskAreaCommand(int stationIdx, StationCommand command) {
|
if (stationIdx < 0 || command == null || command.getTaskNo() == null || command.getTargetStaNo() == null) {
|
return false;
|
}
|
OperateResultExOne<byte[]> resultTask = siemensNet.Read("DB13." + (stationIdx * TASK_AREA_LENGTH), (short) TASK_AREA_LENGTH);
|
if (!resultTask.IsSuccess || resultTask.Content == null) {
|
return false;
|
}
|
for (int slotIdx = 1; slotIdx <= TASK_AREA_SLOT_COUNT; slotIdx++) {
|
int offset = slotIdx * TASK_AREA_SLOT_SIZE;
|
int taskNo = siemensNet.getByteTransform().TransInt32(resultTask.Content, offset);
|
int targetPoint = siemensNet.getByteTransform().TransInt16(resultTask.Content, offset + 6);
|
if (command.getTaskNo().equals(taskNo) && command.getTargetStaNo().equals(targetPoint)) {
|
return true;
|
}
|
}
|
return false;
|
}
|
|
private int findIndex(Integer stationId) {
|
for (int i = 0; i < statusList.size(); i++) {
|
ZyStationStatusEntity statusEntity = statusList.get(i);
|
if (statusEntity.getStationId().equals(stationId)) {
|
return i;
|
}
|
}
|
return -1;
|
}
|
|
}
|