| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | @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; |
| | |
| | | } |
| | | |
| | | 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(); |
| | | } |
| | |
| | | statusList.sort(Comparator.comparing(ZyStationStatusEntity::getStationId)); |
| | | } |
| | | barcodeOriginList = basDevp.getBarcodeStationList$(); |
| | | inStationOriginList = sortStationObjModelsByStationId(basDevp.getInStationList$()); |
| | | } |
| | | |
| | | if (siemensNet == null) { |
| | |
| | | |
| | | 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)); // 工作号 |
| | |
| | | |
| | | 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]) { |
| | |
| | | statusEntity.setPalletHeight(palletHeight);//高低信号 |
| | | |
| | | statusEntity.setError(0);//默认无报警 |
| | | statusEntity.setErrorMsg(""); |
| | | |
| | | statusEntity.setTaskWriteIdx((int) siemensNet.getByteTransform().TransInt16(result.Content, i * 10 + 8));//任务可写区 |
| | | fillTaskBufferStatus(taskBufferRaw, i, statusEntity); |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | // 报警信息 |
| | | // 条码站报警信息 |
| | | OperateResultExOne<byte[]> result4 = siemensNet.Read("DB103.2", (short) (barcodeOriginList.size() * 2)); |
| | | if (result4.IsSuccess) { |
| | | for (int i = 0; i < barcodeOriginList.size(); i++) { |
| | |
| | | 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); |
| | | } |
| | | } |
| | | |
| | |
| | | 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] = command.getStationId().shortValue(); |
| | | 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); |
| | |
| | | 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; |
| | | } |
| | | |
| | |
| | | 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) { |
| | |
| | | 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); |
| | | } |
| | | |
| | | } |