Junjie
18 小时以前 9ea4fda8bd24942bedd72de72c2983cbaed6af65
src/main/java/com/zy/core/network/real/ZyStationV4RealConnect.java
@@ -6,7 +6,7 @@
import HslCommunication.Profinet.Siemens.SiemensS7Net;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.core.common.DateUtils;
import com.core.common.SpringUtils;
import com.zy.asrs.entity.BasDevp;
@@ -18,11 +18,13 @@
import com.zy.core.model.CommandResponse;
import com.zy.core.model.StationObjModel;
import com.zy.core.model.command.StationCommand;
import com.zy.core.model.protocol.StationTaskBufferItem;
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.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
@@ -34,8 +36,40 @@
@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 static final String[] CONVEYOR_COMMON_ALARM_MESSAGES = {
            "急停",
            "低位断路器断开",
            "低位变频器故障",
            "输送运行超时",
            "顶升运行超时",
            "申请任务超时",
            "托盘突出报警",
            "任务运行超时",
            "FWD旋转限位报警",
            "REV旋转限位报警",
            "扫码检验异常",
            "安全门打开报警",
            "任务重复报警",
            "入站过程中前置条件异常",
            "入站前置条件等待超时",
            "出站过程中前置条件异常",
            "出站前置条件等待超时",
            "高位断路器断开",
            "高位变频器故障",
            "顶升限位信号异常",
            "入站运行中,上站同步运行请求消失",
            "出站完成后,仍然检测到托盘",
            "入站完成后,没有检测到托盘",
            "下站站号异常",
            "路径查询异常"
    };
    private List<ZyStationStatusEntity> statusList;
    private List<StationObjModel> barcodeOriginList;
    private List<StationObjModel> inStationOriginList;
    private SiemensS7Net siemensNet;
    private DeviceConfig deviceConfig;
    private RedisUtil redisUtil;
@@ -83,7 +117,7 @@
            }
            BasDevp basDevp = basDevpService
                    .selectOne(new EntityWrapper<BasDevp>().eq("devp_no", deviceConfig.getDeviceNo()));
                    .getOne(new QueryWrapper<BasDevp>().eq("devp_no", deviceConfig.getDeviceNo()));
            if (basDevp == null) {
                return Collections.emptyList();
            }
@@ -93,6 +127,7 @@
                statusList.sort(Comparator.comparing(ZyStationStatusEntity::getStationId));
            }
            barcodeOriginList = basDevp.getBarcodeStationList$();
            inStationOriginList = sortStationObjModelsByStationId(basDevp.getInStationList$());
        }
        if (siemensNet == null) {
@@ -101,6 +136,7 @@
        OperateResultExOne<byte[]> result = siemensNet.Read("DB100.0", (short) (statusList.size() * 10));
        if (result.IsSuccess) {
            byte[] taskBufferRaw = readTaskBufferRaw();
            for (int i = 0; i < statusList.size(); i++) {
                ZyStationStatusEntity statusEntity = statusList.get(i); // 站点编号
                statusEntity.setTaskNo(siemensNet.getByteTransform().TransInt32(result.Content, i * 10)); // 工作号
@@ -131,8 +167,10 @@
                statusEntity.setPalletHeight(palletHeight);//高低信号
                statusEntity.setError(0);//默认无报警
                statusEntity.setErrorMsg("");
                statusEntity.setTaskWriteIdx((int) siemensNet.getByteTransform().TransInt16(result.Content, i * 10 + 8));//任务可写区
                fillTaskBufferStatus(taskBufferRaw, i, statusEntity);
            }
        }
@@ -163,7 +201,7 @@
            }
        }
        // 报警信息
        // 条码站报警信息
        OperateResultExOne<byte[]> result4 = siemensNet.Read("DB103.2", (short) (barcodeOriginList.size() * 2));
        if (result4.IsSuccess) {
            for (int i = 0; i < barcodeOriginList.size(); i++) {
@@ -201,12 +239,35 @@
                    sb.append("扫码异常;");
                }
                if(sb.length() > 0) {
                    barcodeEntity.setError(1);
                }else {
                    barcodeEntity.setError(0);
                applyAlarmMessage(barcodeEntity, sb.toString());
            }
        }
        // 输送站点通用报警信息
        OperateResultExOne<byte[]> result5 = siemensNet.Read("DB25.0", (short) (statusList.size() * 4));
        if (result5.IsSuccess) {
            for (int i = 0; i < statusList.size(); i++) {
                ZyStationStatusEntity statusEntity = statusList.get(i); // 站点编号
                boolean[] status1 = siemensNet.getByteTransform().TransBool(result5.Content, i * 4, 1);
                boolean[] status2 = siemensNet.getByteTransform().TransBool(result5.Content, i * 4 + 1, 1);
                boolean[] status3 = siemensNet.getByteTransform().TransBool(result5.Content, i * 4 + 2, 1);
                boolean[] status4 = siemensNet.getByteTransform().TransBool(result5.Content, i * 4 + 3, 1);
                String alarmMsg = buildConveyorCommonAlarmMessage(status1, status2, status3, status4);
                applyAlarmMessage(statusEntity, mergeAlarmMessages(statusEntity.getErrorMsg(), alarmMsg));
            }
        }
        // 出入库模式
        OperateResultExOne<byte[]> result6 = siemensNet.Read("DB167.2", (short) (inStationOriginList.size() * 2));
        if (result6.IsSuccess) {
            for (int i = 0; i < inStationOriginList.size(); i++) {
                ZyStationStatusEntity inStationEntity = findStatusEntityByInStationIdx(i);
                if (inStationEntity == null) {
                    continue;
                }
                barcodeEntity.setErrorMsg(sb.toString());
                Integer ioMode = normalizeIoMode((int) siemensNet.getByteTransform().TransInt16(result6.Content, i * 2));
                inStationEntity.setIoMode(ioMode);
            }
        }
@@ -221,19 +282,30 @@
            return commandResponse;
        }
        int taskWriteIdx = getTaskWriteIdx(command.getStationId());
        if (taskWriteIdx == -1) {
        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;
        }
        int useTaskWriteIdx = getTaskWriteIdx(stationIdx, taskWriteIdx);
        if (useTaskWriteIdx == -1) {
            commandResponse.setMessage("命令下发超时,无法找到可用下发区域");
            return commandResponse;
        }
        int stationIdx = findIndex(command.getStationId());
        int taskBaseOffset = stationIdx * TASK_AREA_LENGTH + (useTaskWriteIdx * TASK_AREA_SLOT_SIZE);
        short[] data = new short[2];
        data[0] = (short) 0;
        data[1] = command.getTargetStaNo().shortValue();
        OperateResult writeTaskNo = siemensNet.Write("DB13." + (stationIdx * 48 + (taskWriteIdx * 12)), command.getTaskNo());
        OperateResult writeTaskNo = siemensNet.Write("DB13." + taskBaseOffset, command.getTaskNo());
        if (!writeTaskNo.IsSuccess) {
            log.error("写入输送线命令失败。站点编号={},站点数据={}", command.getTaskNo(), JSON.toJSON(command));
            commandResponse.setResult(false);
@@ -241,16 +313,54 @@
            return commandResponse;
        }
        OperateResult writeData = siemensNet.Write("DB13." + (stationIdx * 48 + (taskWriteIdx * 12 + 4)), data);
        if (!writeData.IsSuccess) {
        OperateResult writeTarget = siemensNet.Write("DB13." + (taskBaseOffset + 6), command.getTargetStaNo().shortValue());
        if (!writeTarget.IsSuccess) {
            log.error("写入输送线命令失败。站点编号={},站点数据={}", command.getTaskNo(), JSON.toJSON(command));
            commandResponse.setResult(false);
            commandResponse.setMessage("命令下发失败,写入数据区域失败");
            commandResponse.setMessage("命令下发失败,写入目标设备号失败");
            return commandResponse;
        }
        log.info("写入输送线命令成功。任务号={},站点数据={}", command.getTaskNo(), JSON.toJSON(command));
        commandResponse.setResult(true);
        return commandResponse;
    }
    @Override
    public CommandResponse clearTaskBufferSlot(Integer deviceNo, Integer stationId, Integer slotIdx) {
        CommandResponse commandResponse = new CommandResponse(false);
        if (stationId == null) {
            commandResponse.setMessage("站点号为空");
            return commandResponse;
        }
        if (slotIdx == null || slotIdx <= 0 || slotIdx > TASK_AREA_SLOT_COUNT) {
            commandResponse.setMessage("缓存区槽位无效");
            return commandResponse;
        }
        getStatus(deviceNo);
        int stationIdx = findIndex(stationId);
        if (stationIdx < 0) {
            commandResponse.setMessage("未找到站点状态");
            return commandResponse;
        }
        int slotBaseOffset = stationIdx * TASK_AREA_LENGTH + slotIdx * TASK_AREA_SLOT_SIZE;
        CommandResponse clearTaskNo = sendOriginCommand("DB13." + slotBaseOffset, new short[]{0, 0});
        if (clearTaskNo == null || !Boolean.TRUE.equals(clearTaskNo.getResult())) {
            commandResponse.setMessage(clearTaskNo == null ? "清空任务号失败" : clearTaskNo.getMessage());
            return commandResponse;
        }
        CommandResponse clearTarget = sendOriginCommand("DB13." + (slotBaseOffset + 6), new short[]{0});
        if (clearTarget == null || !Boolean.TRUE.equals(clearTarget.getResult())) {
            commandResponse.setMessage(clearTarget == null ? "清空目标站失败" : clearTarget.getMessage());
            return commandResponse;
        }
        commandResponse.setResult(true);
        commandResponse.setMessage("缓存区槽位清理成功");
        return commandResponse;
    }
@@ -299,28 +409,67 @@
        return null;
    }
    private int getTaskWriteIdx(int stationId) {
        int useIdx = -1;
    private ZyStationStatusEntity findStatusEntityByInStationIdx(Integer idx) {
        Integer stationId = findInStationIdByOrder(inStationOriginList, idx);
        int stationIdx = findIndex(stationId);
        if (stationIdx != -1) {
            ZyStationStatusEntity statusEntity = statusList.get(stationIdx);
            Integer taskWriteIdx = statusEntity.getTaskWriteIdx();
            if (taskWriteIdx > 0) {
                OperateResultExOne<byte[]> resultTask = siemensNet.Read("DB13." + (stationId * 48), (short) 48);
                if (resultTask.IsSuccess) {
                    int taskNo = siemensNet.getByteTransform().TransInt32(resultTask.Content, taskWriteIdx * 12);
                    int startPoint = siemensNet.getByteTransform().TransInt16(resultTask.Content, taskWriteIdx * 12 + 4);
                    int targetPoint = siemensNet.getByteTransform().TransInt16(resultTask.Content, taskWriteIdx * 12 + 6);
                    if (taskNo == 0 && startPoint == 0 && targetPoint == 0) {
                        useIdx = taskWriteIdx;
                    }
                }
        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 targetPoint = siemensNet.getByteTransform().TransInt16(resultTask.Content, taskWriteIdx * TASK_AREA_SLOT_SIZE + 6);
            if (taskNo == 0 && targetPoint == 0) {
                useIdx = taskWriteIdx;
            }
        }
        return useIdx;
    }
    private byte[] readTaskBufferRaw() {
        int totalLength = statusList == null ? 0 : statusList.size() * TASK_AREA_LENGTH;
        if (totalLength <= 0) {
            return null;
        }
        OperateResultExOne<byte[]> resultTask = siemensNet.Read("DB13.0", (short) totalLength);
        if (!resultTask.IsSuccess || resultTask.Content == null || resultTask.Content.length < totalLength) {
            return null;
        }
        return resultTask.Content;
    }
    private void fillTaskBufferStatus(byte[] taskBufferRaw, int stationIdx, ZyStationStatusEntity statusEntity) {
        if (statusEntity == null || stationIdx < 0 || taskBufferRaw == null) {
            statusEntity.setTaskBufferItems(new ArrayList<>());
            return;
        }
        List<StationTaskBufferItem> itemList = new ArrayList<>();
        int stationOffset = stationIdx * TASK_AREA_LENGTH;
        if (stationOffset + TASK_AREA_LENGTH > taskBufferRaw.length) {
            statusEntity.setTaskBufferItems(itemList);
            return;
        }
        for (int slotIdx = 1; slotIdx <= TASK_AREA_SLOT_COUNT; slotIdx++) {
            int offset = stationOffset + (slotIdx * TASK_AREA_SLOT_SIZE);
            int taskNo = siemensNet.getByteTransform().TransInt32(taskBufferRaw, offset);
            int targetPoint = siemensNet.getByteTransform().TransInt16(taskBufferRaw, offset + 6);
            StationTaskBufferItem item = new StationTaskBufferItem();
            item.setSlotIdx(slotIdx);
            item.setTaskNo(taskNo);
            item.setTargetStaNo(targetPoint);
            itemList.add(item);
        }
        statusEntity.setTaskBufferItems(itemList);
    }
    private int findIndex(Integer stationId) {
@@ -333,4 +482,77 @@
        return -1;
    }
    static String buildConveyorCommonAlarmMessage(boolean[] status1, boolean[] status2, boolean[] status3, boolean[] status4) {
        StringBuilder sb = new StringBuilder();
        appendConveyorCommonAlarmMessages(sb, status1, 0);
        appendConveyorCommonAlarmMessages(sb, status2, 8);
        appendConveyorCommonAlarmMessages(sb, status3, 16);
        appendConveyorCommonAlarmMessages(sb, status4, 24);
        return sb.toString();
    }
    static String mergeAlarmMessages(String currentMsg, String appendMsg) {
        String current = currentMsg == null ? "" : currentMsg;
        String append = appendMsg == null ? "" : appendMsg;
        if (append.isEmpty()) {
            return current;
        }
        if (current.isEmpty()) {
            return append;
        }
        if (!current.endsWith(";")) {
            current += ";";
        }
        return current + append;
    }
    static Integer normalizeIoMode(Integer rawMode) {
        if (rawMode == null) {
            return null;
        }
        if (rawMode == 1 || rawMode == 2) {
            return rawMode;
        }
        return null;
    }
    static Integer findInStationIdByOrder(List<StationObjModel> inStationOriginList, Integer orderIdx) {
        if (inStationOriginList == null || orderIdx == null || orderIdx < 0 || orderIdx >= inStationOriginList.size()) {
            return null;
        }
        StationObjModel stationObjModel = inStationOriginList.get(orderIdx);
        return stationObjModel == null ? null : stationObjModel.getStationId();
    }
    static List<StationObjModel> sortStationObjModelsByStationId(List<StationObjModel> stationObjModels) {
        if (stationObjModels == null) {
            return Collections.emptyList();
        }
        stationObjModels.sort(Comparator.comparing(StationObjModel::getStationId, Comparator.nullsLast(Integer::compareTo)));
        return stationObjModels;
    }
    private static void appendConveyorCommonAlarmMessages(StringBuilder sb, boolean[] status, int startIdx) {
        if (status == null) {
            return;
        }
        int limit = Math.min(status.length, 8);
        for (int i = 0; i < limit; i++) {
            int alarmIdx = startIdx + i;
            if (!status[i] || alarmIdx >= CONVEYOR_COMMON_ALARM_MESSAGES.length) {
                continue;
            }
            sb.append(CONVEYOR_COMMON_ALARM_MESSAGES[alarmIdx]).append(";");
        }
    }
    private static void applyAlarmMessage(ZyStationStatusEntity statusEntity, String alarmMsg) {
        if (statusEntity == null) {
            return;
        }
        String message = alarmMsg == null ? "" : alarmMsg;
        statusEntity.setError(message.isEmpty() ? 0 : 1);
        statusEntity.setErrorMsg(message);
    }
}