#
lty
昨天 276d837c0bb808e6d93ac7c7ba6abe654c75552e
#
3个文件已添加
6个文件已修改
892 ■■■■ 已修改文件
src/main/java/com/zy/asrs/controller/OpenController.java 157 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/param/InboundTaskApplyParam.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/param/TaskCreateParam.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/param/TaskStatusFeedbackParam.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/OpenService.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/OpenServiceImpl.java 265 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/CrnProtocol.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/core/model/protocol/StaProtocol.java 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/OpenController.java
@@ -9,23 +9,35 @@
import com.zy.asrs.entity.WrkMast;
import com.zy.asrs.entity.param.ArmPrecomputeParam;
import com.zy.asrs.service.OpenService;
import com.zy.asrs.service.impl.WrkMastServiceImpl;
import com.zy.common.web.BaseController;
import com.zy.core.cache.RgvStatusCache;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.SlaveType;
import com.zy.core.model.CrnSlave;
import com.zy.core.model.DevpSlave;
import com.zy.core.model.protocol.CrnProtocol;
import com.zy.core.model.protocol.RgvProtocol;
import com.zy.core.model.protocol.StaProtocol;
import com.zy.core.properties.SlaveProperties;
import com.zy.core.thread.SiemensCrnThread;
import com.zy.core.thread.SiemensDevpThread;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.*;
import com.zy.asrs.entity.param.TaskCreateParam;
/**
 * Created by vincent on 2024/10/16
 */
@Slf4j
@RestController
@RequestMapping("open/hd")
@RequestMapping("open/")
public class OpenController extends BaseController {
    private static final boolean auth = true;
@@ -35,6 +47,11 @@
    @Autowired
    private OpenService openService;
    @Autowired
    private SlaveProperties slaveProperties;
    @Autowired
    private WrkMastServiceImpl wrkMastService;
    /**
     * 添加出库单
@@ -65,6 +82,138 @@
        return R.ok().add(param);
    }
    /**
     * 设备状态
     */
    @PostMapping("/deviceStatus")
    @AppAuth(memo = "设备状态获取")
    public R deviceStatus(
            @RequestHeader(required = false) String appkey,
            HttpServletRequest request) {
        try {
            auth(appkey, null, request);
        } catch (Exception e) {
            return new R(403, e.getMessage());
        }
        // 1. 站点
        List<Map<String, Object>> devList = new ArrayList<>();
        if (slaveProperties.getDevp() != null) {
            for (DevpSlave devpSlave : slaveProperties.getDevp()) {
                SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devpSlave.getId());
                if (devpThread != null && devpThread.getStation() != null) {
                    for (StaProtocol staProtocol : devpThread.getStation().values()) {
                        Map<String, Object> dev = new HashMap<>();
                        dev.put("devNo", staProtocol.getSiteId());
                        dev.put("inEnable", staProtocol.isInEnable() ? "1" : "0");
                        dev.put("outEnable", staProtocol.isOutEnable() ? "1" : "0");
                        dev.put("autoing", staProtocol.isAutoing() ? "1" : "0");
                        dev.put("loading", staProtocol.isLoading() ? "1" : "0");
                        dev.put("wrkNo", staProtocol.getWorkNo());
                        dev.put("barcode", staProtocol.getBarcode());
                        dev.put("devErr", staProtocol.getErrorDev$());
                        dev.put("devErrM", staProtocol.getExceptions());
                        devList.add(dev);
                    }
                }
            }
        }
        devList.sort(Comparator.comparingInt(m -> (Integer) m.get("devNo")));
        // 2. 堆垛机
        List<Map<String, Object>> crnList = new ArrayList<>();
        if (slaveProperties.getCrn() != null) {
            for (CrnSlave crnSlave : slaveProperties.getCrn()) {
                SiemensCrnThread crnThread = (SiemensCrnThread) SlaveConnection.get(SlaveType.Crn, crnSlave.getId());
                if (crnThread != null && crnThread.getCrnProtocol() != null) {
                    CrnProtocol crnProtocol = crnThread.getCrnProtocol();
                    Map<String, Object> crn = new HashMap<>();
                    crn.put("crnNo", crnProtocol.getCrnNo());
                    crn.put("crnNoH", crnProtocol.getCrnNo());
                    crn.put("crnSts", crnProtocol.getMode());
                    crn.put("wrkNo", crnProtocol.getTaskNo());
                    crn.put("crnErr", crnProtocol.getAlarm());
                    crn.put("crnErrM", crnProtocol.getExceptions());
                    WrkMast wrkMast = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no",crnProtocol.getTaskNo()));
                    crn.put("frmLocno",wrkMast != null ? wrkMast.getSourceLocNo():null);
                    crn.put("frmSta",wrkMast != null ? wrkMast.getSourceStaNo():0);
                    crn.put("toSta", wrkMast != null? wrkMast.getStaNo():0);
                    crn.put("toLocno", wrkMast != null ? wrkMast.getLocNo():null);
                    crnList.add(crn);
                }
            }
        }
        crnList.sort(Comparator.comparingInt(m -> (Integer) m.get("crnNo")));
        // 3. 穿梭车
        List<Map<String, Object>> steList = new ArrayList<>();
        Map<Integer, RgvProtocol> rgvMap = RgvStatusCache.getAllRgvStatus();
        if (rgvMap != null) {
            for (RgvProtocol rgvProtocol : rgvMap.values()) {
                Map<String, Object> ste = new HashMap<>();
                ste.put("steNo", rgvProtocol.getRgvNo());
                ste.put("crnSts", rgvProtocol.getStatusType() != null ? rgvProtocol.getStatusType().id : 1);
                ste.put("wrkNo", rgvProtocol.getTaskNo());
                ste.put("steErr", rgvProtocol.getAlarm$());
                ste.put("steErrM", rgvProtocol.getAlarmM());
                steList.add(ste);
            }
        }
        steList.sort(Comparator.comparingInt(m -> (Integer) m.get("steNo")));
        R r =  R.ok();
        r.put("devList", devList);
        r.put("crnList", crnList);
        r.put("steList", steList);
        return r;
    }
    /**
     * 任务下发
     */
    @PostMapping("/taskCreate")
    @AppAuth(memo = "任务下发")
    public R taskCreate(@RequestHeader(required = false) String appkey,
                        @RequestBody TaskCreateParam param,
                        HttpServletRequest request) {
        try {
            auth(appkey, param, request);
        } catch (Exception e) {
            return new R(403, e.getMessage());
        }
        if (Cools.isEmpty(param)) {
            return R.parse(BaseRes.PARAM);
        }
        if (Cools.isEmpty(param.getTaskNo())) {
            return R.error("工作号[taskNo]不能为空");
        }
        if (Cools.isEmpty(param.getBarcode())) {
             return R.error("容器编码[barcode]不能为空");
        }
        if (Cools.isEmpty(param.getStartPoint())) {
             return R.error("起点[startPoint]不能为空");
        }
        if (Cools.isEmpty(param.getTargetPoint())) {
             return R.error("目标点[targetPoint]不能为空");
        }
        try {
            boolean result = openService.taskCreate(param);
            if (result) {
                return R.ok("任务下发成功");
            } else {
                return R.error("任务下发失败");
            }
        } catch (Exception e) {
            log.error("任务下发异常", e);
            return R.error("任务下发异常: " + e.getMessage());
        }
    }
    private void auth(String appkey, Object obj, HttpServletRequest request) {
//        log.info("{}接口被访问;appkey:{};请求数据:{}", "open/sensorType/list/auth/v1", appkey, JSON.toJSONString(obj));
src/main/java/com/zy/asrs/entity/param/InboundTaskApplyParam.java
New file
@@ -0,0 +1,25 @@
package com.zy.asrs.entity.param;
import lombok.Data;
/**
 * 任务申请参数
 */
@Data
public class InboundTaskApplyParam {
    /**
     * 容器编码
     */
    private String barcode;
    /**
     * 入库站编号
     */
    private String stationCode;
    /**
     * 空满板 (0:空板, 1:满板 - 根据业务逻辑约定)
     */
    private Integer status;
}
src/main/java/com/zy/asrs/entity/param/TaskCreateParam.java
New file
@@ -0,0 +1,94 @@
package com.zy.asrs.entity.param;
import lombok.Data;
import java.util.List;
import java.math.BigDecimal;
/**
 * 任务创建参数
 */
@Data
public class TaskCreateParam {
    /**
     * 工作号
     */
    private String taskNo;
    /**
     * 1:出库,2:入库 3:移库
     * 11:空板出库,12:空板入库
     * 21:拣选出库 22:拣选入库
     * 31:盘点出库 32:盘点入库
     */
    private Integer ioType;
    /**
     * 优先级
     */
    private Integer taskPriority;
    /**
     * 容器编码
     */
    private String barcode;
    /**
     * 起点
     */
    private String startPoint;
    /**
     * 目标点
     */
    private String targetPoint;
    private String sourceLocNo;
    private String targetLocNo;
    /**
     * 备注
     */
    private String memo;
    /**
     * 明细列表
     */
    private List<Detl> detlList;
    @Data
    public static class Detl {
        /**
         * 工作号
         */
        private String taskNo;
        /**
         * 物料编码
         */
        private String matnr;
        /**
         * 批次(默认为当前日期,相同批次自动合并)
         */
        private String batch;
        /**
         * 容器编码(明细需要一致)
         */
        private String barcode;
        /**
         * 数量
         */
        private BigDecimal anfme;
        /**
         * 备注
         */
        private String memo;
    }
}
src/main/java/com/zy/asrs/entity/param/TaskStatusFeedbackParam.java
New file
@@ -0,0 +1,39 @@
package com.zy.asrs.entity.param;
import lombok.Data;
import java.util.Date;
/**
 * 任务状态反馈参数
 */
@Data
public class TaskStatusFeedbackParam {
    /**
     * 工作号
     */
    private String taskNo;
    /**
     * 1:取消
     * 2:完结
     * 3:拣选、盘点出库上报(任务未结束,需要回库)
     */
    private Integer status;
    /**
     * 1:出库,2:移库,3:入库
     */
    private Integer ioType;
    /**
     * 托盘码
     */
    private String barcode;
    /**
     * 上报时间
     */
    private Date reportTime;
}
src/main/java/com/zy/asrs/service/OpenService.java
@@ -2,7 +2,24 @@
import com.core.common.R;
import com.zy.asrs.entity.param.ArmPrecomputeParam;
import com.zy.asrs.entity.param.TaskCreateParam;
public interface OpenService {
    /**
     * 任务状态反馈上报
     * @param taskNo 工作号
     * @param status 状态 1:取消 2:完结 3:拣选、盘点出库上报
     * @param ioType 类型 1:出库,2:移库,3:入库
     * @param barcode 托盘码
     * @return 是否成功
     */
    boolean reportTaskStatus(String taskNo, Integer status, Integer ioType, String barcode);
    /**
     * 任务下发
     * @param param 任务参数
     * @return 是否成功
     */
    boolean taskCreate(TaskCreateParam param);
}
src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java
@@ -10,6 +10,7 @@
import com.zy.asrs.domain.enums.LedErrorAreaType;
import com.zy.asrs.domain.enums.TaskStatusType;
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.param.InboundTaskApplyParam;
import com.zy.asrs.mapper.*;
import com.zy.asrs.service.*;
import com.zy.asrs.utils.*;
@@ -82,6 +83,8 @@
    private BasDevpPositionService basDevpPositionService;
    @Autowired
    private TaskWrkService taskWrkService;
    @Autowired
    private OpenService openService;
    @Value("${wms.url}")
    private String wmsUrl;
@@ -258,45 +261,31 @@
                    try {
                        LocTypeDto locTypeDto = new LocTypeDto(staProtocol);
                        SearchLocParam param = new SearchLocParam();
                        param.setBarcode(barcode);
                        param.setIoType(1);
                        param.setSourceStaNo(inSta.getStaNo());
                        param.setLocType1(locTypeDto.getLocType1());
                        // 替换为新的任务申请接口
                        InboundTaskApplyParam applyParam = new InboundTaskApplyParam();
                        applyParam.setBarcode(barcode);
                        applyParam.setStationCode(String.valueOf(inSta.getStaNo()));
                        applyParam.setStatus(1); // 1:满板
                        String response = new HttpHandler.Builder()
                                .setUri(wmsUrl)
                                .setPath("/rpc/pakin/loc/v1")
                                .setJson(JSON.toJSONString(param))
                                .setPath("/inboundTaskApply")
                                .setJson(JSON.toJSONString(applyParam))
                                .build()
                                .doPost();
                        // 解析响应,只确认申请是否成功
                        JSONObject jsonObject = JSON.parseObject(response);
                        if (jsonObject.getInteger("code").equals(200)) {
                            StartupDto dto = jsonObject.getObject("data", StartupDto.class);
//                            LedThread ledThread = (LedThread) SlaveConnection.get(SlaveType.Led, inSta.getLed());
                            barcodeThread.setBarcode("");
                            staProtocol.setWorkNo(dto.getWorkNo());
//                            if(Cools.isEmpty(dto.getRgvNo()) || dto.getRgvNo() <= 0) {
//                                staProtocol.setStaNo(607);//607
//                            } else {//如果存在RGV编号,说明需要RGV接驳,先下发任务到RGV源站
//                            staProtocol.setStaNo(dto.getRgvSstaNo().shortValue());
                            staProtocol.setStaNo(wrkMast.getStaNoSou$().shortValue());
//                            }
                            devpThread.setPakMk(staProtocol.getSiteId(), false,283);
                        if (jsonObject != null && jsonObject.getInteger("code") != null && jsonObject.getInteger("code") == 200) {
                            log.info("入库任务申请成功,等待WMS下发任务。条码:{},站点:{}", barcode, inSta.getStaNo());
                            staProtocol.setWorkNo(9998);//设置为9998等待上位机下发任务/9997是空板入库判断,待下发时也写入9998
                            boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                            if (!result) {
                                LedErrorThreadUtil.ledErrorThread("更新plc站点信息失败!站点号:"+inSta.getStaNo(),inSta.getLed(), LedErrorAreaType.ONE_OTHER.getDesc());
                                throw new CoolException("更新plc站点信息失败");
                            }
                        } else {
                            // 获取工作号
                            //                            // 获取工作号
                            int workNo = commonService.getWorkNo(3);
                            staProtocol.setWorkNo(workNo);
@@ -306,8 +295,50 @@
                            boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                            // led 异常显示
                            LedErrorThreadUtil.ledErrorThread("入库请求失败"+jsonObject.getInteger("code"),inSta.getLed(), LedErrorAreaType.ONE_OTHER.getDesc());
                            log.error("请求接口失败!!!url:{};request:{};response:{}", wmsUrl + "/rpc/pakin/loc/v1", JSON.toJSONString(param), response);
                            log.error("请求接口失败!!!url:{};request:{};response:{}", wmsUrl + "/inboundTaskApply", JSON.toJSONString(applyParam), response);
                        }
                        // 原有逻辑注释掉
//                        LocTypeDto locTypeDto = new LocTypeDto(staProtocol);
//
//                        SearchLocParam param = new SearchLocParam();
//                        param.setBarcode(barcode);
//                        param.setIoType(1);
//                        param.setSourceStaNo(inSta.getStaNo());
//                        param.setLocType1(locTypeDto.getLocType1());
//                        String response = new HttpHandler.Builder()
//                                .setUri(wmsUrl)
//                                .setPath("/rpc/pakin/loc/v1")
//                                .setJson(JSON.toJSONString(param))
//                                .build()
//                                .doPost();
//                        JSONObject jsonObject = JSON.parseObject(response);
//                        if (jsonObject.getInteger("code").equals(200)) {
//                            StartupDto dto = jsonObject.getObject("data", StartupDto.class);
//
//                            barcodeThread.setBarcode("");
//                            staProtocol.setWorkNo(dto.getWorkNo());
//                            staProtocol.setStaNo(wrkMast.getStaNoSou$().shortValue());
//
//                            devpThread.setPakMk(staProtocol.getSiteId(), false,283);
//                            boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                            if (!result) {
//                                LedErrorThreadUtil.ledErrorThread("更新plc站点信息失败!站点号:"+inSta.getStaNo(),inSta.getLed(), LedErrorAreaType.ONE_OTHER.getDesc());
//                                throw new CoolException("更新plc站点信息失败");
//                            }
//                        } else {
//                            // 获取工作号
//                            int workNo = commonService.getWorkNo(3);
//
//                            staProtocol.setWorkNo(workNo);
//                            staProtocol.setStaNo(inSta.getBackSta().shortValue());
//
//                            devpThread.setPakMk(staProtocol.getSiteId(), false,201);
//                            boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
//                            // led 异常显示
//                            LedErrorThreadUtil.ledErrorThread("入库请求失败"+jsonObject.getInteger("code"),inSta.getLed(), LedErrorAreaType.ONE_OTHER.getDesc());
//                            log.error("请求接口失败!!!url:{};request:{};response:{}", wmsUrl + "/rpc/pakin/loc/v1", JSON.toJSONString(param), response);
//                        }
                    } catch (Exception e) {
                        e.printStackTrace();
@@ -337,36 +368,35 @@
                }
                // 站点条件判断
                if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.isInEnable()
                        && staProtocol.isEmptyMk() && ((staProtocol.getWorkNo() > 9000 && staProtocol.getWorkNo() <= 9999) || staProtocol.getWorkNo()==0)  && staProtocol.isPakMk()) {
                        && staProtocol.isEmptyMk() && ((staProtocol.getWorkNo() > 9000 && staProtocol.getWorkNo() <= 9997) || staProtocol.getWorkNo()==0)  && staProtocol.isPakMk()) {
                    try {
                        LocTypeDto locTypeDto = new LocTypeDto(staProtocol);
                        SearchLocParam param = new SearchLocParam();
                        param.setIoType(10);
                        param.setSourceStaNo(emptyInSta.getStaNo());
                        param.setLocType1(locTypeDto.getLocType1());
                        InboundTaskApplyParam applyParam = new InboundTaskApplyParam();
                        applyParam.setBarcode(null);
                        applyParam.setStationCode(String.valueOf(emptyInSta.getStaNo()));
                        applyParam.setStatus(0); // 1:满板
                        String response = new HttpHandler.Builder()
                                .setUri(wmsUrl)
                                .setPath("/rpc/pakin/loc/v1")
                                .setJson(JSON.toJSONString(param))
                                .setPath("/inboundTaskApply")
                                .setJson(JSON.toJSONString(applyParam))
                                .build()
                                .doPost();
                        JSONObject jsonObject = JSON.parseObject(response);
                        if (jsonObject.getInteger("code").equals(200)) {
                            StartupDto dto = jsonObject.getObject("data", StartupDto.class);
                            // 更新站点信息 且 下发plc命令
                            staProtocol.setWorkNo(dto.getWorkNo());
                            staProtocol.setStaNo(dto.getStaNoSou$(dto.getStaNo(),staProtocol.getSiteId()).shortValue());
                            devpThread.setPakMk(staProtocol.getSiteId(), false,4087);
                        // 解析响应,只确认申请是否成功
                        JSONObject jsonObject = JSON.parseObject(response);
                        if (jsonObject != null && jsonObject.getInteger("code") != null && jsonObject.getInteger("code") == 200) {
                            log.info("入库任务申请成功,等待WMS下发任务,站点:{}",emptyInSta.getStaNo());
                            staProtocol.setWorkNo(9998);//设置为9998等待上位机下发任务
                            boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                            if (!result) {
                                LedErrorThreadUtil.ledErrorThread("更新plc站点信息失败!站点号:"+emptyInSta.getStaNo(),emptyInSta.getLed(), LedErrorAreaType.ONE_OTHER.getDesc());
                                throw new CoolException("更新plc站点信息失败");
                            }
                        } else {
                            log.error("请求接口失败!!!url:{};request:{};response:{}", wmsUrl + "/rpc/pakin/loc/v1", JSON.toJSONString(param), response);
                            log.error("请求接口失败!!!url:{};request:{};response:{}", wmsUrl + "/inboundTaskApply", JSON.toJSONString(applyParam), response);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
@@ -545,6 +575,10 @@
                        if (wrkMastMapper.updateById(wrkMast) != 0) {
                            // 复位堆垛机
                            crnThread.setResetFlag(true);
                            if(wrkMast.getIoType() == 103 || wrkMast.getIoType() == 107) { //拣料出库任务状态上报,其他上报在wms任务完成定时任务中
                                openService.reportTaskStatus(String.valueOf(wrkMast.getWrkNo()),3,1,wrkMast.getBarcode());
                            }
                        } else {
                            log.error("更新工作档的工作状态为14失败!!! [工作号:{}]", wrkMast.getWrkNo());
                        }
src/main/java/com/zy/asrs/service/impl/OpenServiceImpl.java
@@ -1,18 +1,36 @@
package com.zy.asrs.service.impl;
import com.core.common.R;
import com.zy.asrs.entity.param.ArmPrecomputeParam;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.zy.asrs.entity.WrkDetl;
import com.zy.asrs.entity.WrkMast;
import com.zy.asrs.entity.param.TaskCreateParam;
import com.zy.asrs.entity.param.TaskStatusFeedbackParam;
import com.zy.asrs.service.ApiLogService;
import com.zy.asrs.service.OpenService;
import com.zy.asrs.service.WrkDetlService;
import com.zy.asrs.service.WrkMastService;
import com.zy.common.service.CommonService;
import com.zy.common.utils.HttpHandler;
import com.zy.core.cache.MessageQueue;
import com.zy.core.cache.SlaveConnection;
import com.zy.core.enums.SlaveType;
import com.zy.core.model.Task;
import com.zy.core.model.protocol.StaProtocol;
import com.zy.core.properties.SlaveProperties;
import com.zy.core.thread.SiemensDevpThread;
import com.zy.core.model.DevpSlave;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
/**
 * Created by vincent on 2022/4/9
@@ -21,5 +39,244 @@
@Service
public class OpenServiceImpl implements OpenService {
    @Value("${wms.url}")
    private String wmsUrl;
    @Autowired
    private ApiLogService apiLogService;
    @Autowired
    private CommonService commonService;
    @Autowired
    private WrkMastService wrkMastService;
    @Autowired
    private WrkDetlService wrkDetlService;
    @Autowired
    private SlaveProperties slaveProperties;
    @Override
    public boolean reportTaskStatus(String taskNo, Integer status, Integer ioType, String barcode) {
        try {
            TaskStatusFeedbackParam param = new TaskStatusFeedbackParam();
            param.setTaskNo(taskNo);
            param.setStatus(status);
            param.setIoType(ioType);
            param.setBarcode(barcode);
            param.setReportTime(new Date());
            Map<String, Object> headers = new HashMap<>();
            headers.put("appkey", "ea1f0459efc02a79f046f982767939ae");
            String response = new HttpHandler.Builder()
                    .setUri(wmsUrl)
                    .setPath("/taskStatusFeedback")
                    .setJson(JSON.toJSONString(param))
                    .setHeaders(headers)
                    .build()
                    .doPost();
            boolean success = false;
            log.info("任务状态反馈上报结果:{}", response);
            if (response != null) {
                try {
                    JSONObject jsonObject = JSON.parseObject(response);
                    // 假设返回code为200表示成功
                    if (jsonObject != null && jsonObject.containsKey("code") && jsonObject.getInteger("code") == 200) {
                        success = true;
                    }
                } catch (Exception e) {
                    log.warn("解析响应失败", e);
                }
            }
            // 记录日志
            try {
                apiLogService.save("任务状态反馈上报",
                        "/taskStatusFeedback",
                        "ea1f0459efc02a79f046f982767939ae",
                        wmsUrl,
                        JSON.toJSONString(param),
                        response,
                        success);
            } catch (Exception e) {
                log.error("保存API日志异常", e);
            }
            return success;
        } catch (Exception e) {
            log.error("任务状态反馈上报异常", e);
        }
        return false;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean taskCreate(TaskCreateParam param) {
        try {
            Integer ioType = 0;
            boolean Inbound = true;
            //1:出库,2:入库 3:移库
            //11:空板出库,12:空板入库
            //21:拣选出库 22:拣选入库
            //31:盘点出库 32:盘点入库
            switch (param.getIoType()){
                case 1:  Inbound = false;break;
                case 2 : Inbound = true;break;
                case 3:  Inbound = false;break;
                case 11: Inbound = false;ioType = 110;break;
                case 12: Inbound = true;break;
                case 21: Inbound = false;ioType = 103;break;
                case 22: Inbound = true;break;
                case 31: Inbound = false;ioType = 107;break;
                case 32: Inbound = true;break;
            }
            // 2. 保存WrkMast
            WrkMast wrkMast = new WrkMast();
            if(param.getIoType() == 2 || param.getIoType() == 12){
                wrkMast.setWrkNo(Integer.valueOf(param.getTaskNo()));
                wrkMast.setIoType(param.getIoType() != 2?10:1);
                wrkMast.setIoPri(param.getTaskPriority() != null ? param.getTaskPriority().doubleValue() : 11.0);
                wrkMast.setBarcode(param.getBarcode());
                wrkMast.setMemo(param.getMemo());
                wrkMast.setSourceStaNo(Integer.valueOf(param.getStartPoint()));
                wrkMast.setStaNo(Integer.valueOf(param.getTargetPoint()));
                wrkMast.setLocNo(param.getTargetLocNo());
                wrkMast.setSourceLocNo(param.getSourceLocNo());
            }else if(param.getIoType() == 22 || param.getIoType() == 32){
                wrkMast = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("barcode",param.getBarcode()));
                wrkMast.setWrkSts(param.getIoType() != 32 ? 53L: 57L);
                wrkMast.setWrkNo(Integer.valueOf(param.getTaskNo()));
                wrkMast.setIoPri(param.getTaskPriority() != null ? param.getTaskPriority().doubleValue() : 11.0);
                wrkMast.setBarcode(param.getBarcode());
                wrkMast.setMemo(param.getMemo());
                wrkMast.setSourceStaNo(Integer.valueOf(param.getStartPoint()));
                wrkMast.setStaNo(Integer.valueOf(param.getTargetPoint()));
                wrkMast.setLocNo(param.getTargetLocNo());
                wrkMast.setSourceLocNo(param.getSourceLocNo());
            }else if(param.getIoType() == 3){
                wrkMast.setWrkNo(Integer.valueOf(param.getTaskNo()));
                wrkMast.setIoType(11);
                wrkMast.setIoPri(param.getTaskPriority() != null ? param.getTaskPriority().doubleValue() : 12.0);
                wrkMast.setBarcode(param.getBarcode());
                wrkMast.setMemo(param.getMemo());
                wrkMast.setSourceStaNo(Integer.valueOf(param.getStartPoint()));
                wrkMast.setStaNo(Integer.valueOf(param.getTargetPoint()));
                wrkMast.setLocNo(param.getTargetLocNo());
                wrkMast.setSourceLocNo(param.getSourceLocNo());
            }else{
                wrkMast.setWrkNo(Integer.valueOf(param.getTaskNo()));
                wrkMast.setIoType(ioType);
                wrkMast.setIoPri(param.getTaskPriority() != null ? param.getTaskPriority().doubleValue() : 11.0);
                wrkMast.setBarcode(param.getBarcode());
                wrkMast.setMemo(param.getMemo());
                wrkMast.setSourceStaNo(Integer.valueOf(param.getStartPoint()));
                wrkMast.setStaNo(Integer.valueOf(param.getTargetPoint()));
                wrkMast.setLocNo(param.getTargetLocNo());
                wrkMast.setSourceLocNo(param.getSourceLocNo());
            }
            if(Inbound){
                wrkMast.setWrkSts(2L);
            }else{
                wrkMast.setWrkSts(11L);
            }
            wrkMast.setAppeTime(new Date());
            wrkMast.setWrkDate(new Date());
            wrkMastService.insert(wrkMast);
            // 3. 保存WrkDetl
            if (param.getDetlList() != null && !param.getDetlList().isEmpty()) {
                for (TaskCreateParam.Detl detl : param.getDetlList()) {
                    WrkDetl wrkDetl = new WrkDetl();
                    wrkDetl.setWrkNo(wrkMast.getWrkNo());
                    wrkDetl.setZpallet(detl.getBarcode());
                    wrkDetl.setMatnr(detl.getMatnr());
                    wrkDetl.setBatch(detl.getBatch());
                    if (detl.getAnfme() != null) {
                        wrkDetl.setAnfme(detl.getAnfme().doubleValue());
                    }
                    wrkDetlService.insert(wrkDetl);
                }
            }
            // 4. 下发给PLC
            if(Inbound){
                writeToPlc(wrkMast);
            }
            // 记录日志
            try {
                apiLogService.save("任务下发",
                        "/taskCreate",
                        "ea1f0459efc02a79f046f982767939ae",
                        "LOCAL",
                        JSON.toJSONString(param),
                        "SUCCESS",
                        true);
            } catch (Exception e) {
                log.error("保存API日志异常", e);
            }
            return true;
        } catch (Exception e) {
            log.error("任务下发异常", e);
             try {
                apiLogService.save("任务下发",
                        "/taskCreate",
                        "ea1f0459efc02a79f046f982767939ae",
                        "LOCAL",
                        JSON.toJSONString(param),
                        "FAIL: " + e.getMessage(),
                        false);
            } catch (Exception ex) {
                // ignore
            }
            throw new RuntimeException(e); // 触发事务回滚
        }
    }
    private void writeToPlc(WrkMast wrkMast) {
        if (wrkMast.getSourceStaNo() == null) {
            log.warn("任务下发缺少源站点: wrkNo={}", wrkMast.getWrkNo());
            return;
        }
        Integer sourceStaNo = wrkMast.getSourceStaNo();
        for (DevpSlave devp : slaveProperties.getDevp()) {
             SiemensDevpThread devpThread = (SiemensDevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId());
             if (devpThread == null) continue;
             // 检查该PLC是否管理该站点
             if (devpThread.getStation().containsKey(sourceStaNo.shortValue())) {
                 StaProtocol staProtocol = devpThread.getStation().get(sourceStaNo.shortValue());
                 if (staProtocol != null && staProtocol.getWorkNo() == 9998) {
                     staProtocol.setWorkNo(wrkMast.getWrkNo());
                     if (wrkMast.getStaNo() != null) {
                        staProtocol.setStaNo(wrkMast.getStaNo().shortValue());
                     }
                     // 下发PLC指令
                     devpThread.setPakMk(staProtocol.getSiteId(), false, 283);
                     boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol));
                     if (result) {
                         log.info("任务下发成功,已写入PLC。WrkNo: {}, Source: {}, Target: {}",
                                 wrkMast.getWrkNo(), wrkMast.getSourceStaNo(), wrkMast.getStaNo());
                     } else {
                         log.error("任务下发失败,写入PLC队列失败。WrkNo: {}", wrkMast.getWrkNo());
                     }
                     return;
                 }
             }
        }
        log.warn("未找到对应的PLC站点或线程: {}", sourceStaNo);
    }
}
src/main/java/com/zy/core/model/protocol/CrnProtocol.java
@@ -189,6 +189,63 @@
    public Float yDuration;
    //堆垛机配置信号--------------------------------------------------------------
    public java.util.List<java.util.Map<String, Object>> getExceptions() {
        java.util.List<java.util.Map<String, Object>> list = new java.util.ArrayList<>();
        if (ibDriveFault) list.add(createException(0, "行走变频器故障"));
        if (ibSupplyFault) list.add(createException(1, "提供变频器故障"));
        if (ibForkDriveFault) list.add(createException(2, "货叉变频器故障"));
        if (ibDriveCircuitFault) list.add(createException(3, "行走断路器故障"));
        if (ibLiftCircuitFault) list.add(createException(4, "提升断路器故障"));
        if (ibForkCircuitFault) list.add(createException(5, "货叉断路器故障"));
        if (ibForwardLimit) list.add(createException(6, "前进限位"));
        if (ibReverseLimit) list.add(createException(7, "后退限位"));
        if (ibDriveStart) list.add(createException(8, "行走原点"));
        if (ibForwardBrakeSpeed) list.add(createException(9, "前进强制低速"));
        if (ibReverseBrakeSpeed) list.add(createException(10, "后退强制低速"));
        if (ibUpLimit) list.add(createException(11, "上升限位"));
        if (ibDownLimit) list.add(createException(12, "下限限位"));
        if (ibUpOrigin) list.add(createException(13, "提升原点"));
        if (ibUpBrakeSpeed) list.add(createException(14, "上升强制低速"));
        if (ibDownBrakeSpeed) list.add(createException(15, "下降强制低速"));
        if (ibPlatformSignal) list.add(createException(16, "载货台探货"));
        if (ibForkMidSignal) list.add(createException(17, "货叉中位信号"));
        if (ibForkLeftLimit) list.add(createException(18, "货叉左极限"));
        if (ibForkRightLimit) list.add(createException(19, "货叉右极限"));
        if (ibFrontOverLimit) list.add(createException(20, "前超限"));
        if (ibRearOverLimit) list.add(createException(21, "后超限"));
        if (ibLeftOverLimit) list.add(createException(22, "左超限"));
        if (ibRightOverLimit) list.add(createException(23, "右超限"));
        if (ibHighOverLimit1) list.add(createException(24, "高超限1"));
        if (ibHighOverLimit2) list.add(createException(25, "高超限2"));
        if (ibHighOverLimit3) list.add(createException(26, "高超限3"));
        if (ibOneExtendLeftLoad1) list.add(createException(27, "一伸左侧探货1"));
        if (ibOneExtendLeftLoad2) list.add(createException(28, "一伸左侧探货2"));
        if (ibOneExtendRightLoad1) list.add(createException(29, "一伸右侧探货1"));
        if (ibOneExtendRightLoad2) list.add(createException(30, "一伸右侧探货2"));
        if (ibTwoExtendLeftLoad1) list.add(createException(31, "二伸左侧探货1"));
        if (ibTwoExtendLeftLoad2) list.add(createException(32, "二伸左侧探货2"));
        if (ibTwoExtendRightLoad1) list.add(createException(33, "二伸右侧探货1"));
        if (ibTwoExtendRightLoad2) list.add(createException(34, "二伸右侧探货2"));
        if (ibSpeedSignal1) list.add(createException(35, "超速信号1"));
        if (ibSpeedSignal2) list.add(createException(36, "超速信号2"));
        if (ibOverweightSignal1) list.add(createException(37, "超重信号1"));
        if (ibOverweightSignal2) list.add(createException(38, "超重信号2"));
        if (ibRopeReleaseSignal1) list.add(createException(39, "松绳信号1"));
        if (ibRopeReleaseSignal2) list.add(createException(40, "松绳信号2"));
        if (ibSafetyClamp) list.add(createException(41, "安全钳"));
        if (ibTightener) list.add(createException(42, "张紧器"));
        if (ibSpeedLimiter) list.add(createException(43, "限速器"));
        if (ibSafetyDoorOpen) list.add(createException(44, "安全门打开"));
        return list;
    }
    private java.util.Map<String, Object> createException(int code, String msg) {
        java.util.Map<String, Object> map = new java.util.HashMap<>();
        map.put("code", code);
        map.put("msg", msg);
        return map;
    }
    // 故障读取锁定标记
    private boolean errorMk = false;
    //写入标记
src/main/java/com/zy/core/model/protocol/StaProtocol.java
@@ -282,80 +282,50 @@
    }
    public String getErrorDev$(){
        if (errorDev.equals("-")){
            boolean back = false;
            String errMsg = "-";
            if (this.isErrOther1()) {
                if (!back){
                    errMsg = "电路保护器断开";
                } else {
                    errMsg = errMsg+"---"+"电路保护器断开";
                }
                back = true;
            }
            if (this.isErrOther2()) {
                if (!back){
                    errMsg = "光电异常";
                } else {
                    errMsg = errMsg+"---"+"光电异常";
                }
                back = true;
            }
            if (this.isErrOther3()) {
                if (!back){
                    errMsg = "运行超时";
                } else {
                    errMsg = errMsg+"---"+"运行超时";
                }
                back = true;
            }
            if (this.isErrOther4()) {
                if (!back){
                    errMsg = "占位超时";
                } else {
                    errMsg = errMsg+"---"+"占位超时";
                }
                back = true;
            }
            if (this.isErrOther5()) {
                if (!back){
                    errMsg = "有任务无货故障";
                } else {
                    errMsg = errMsg+"---"+"有任务无货故障";
                }
                back = true;
            }
            if (this.isErrOther6()) {
                if (!back){
                    errMsg = "变频器故障";
                } else {
                    errMsg = errMsg+"---"+"变频器故障";
                }
                back = true;
            }
            if (this.isErrOther7()) {
                if (!back){
                    errMsg = "接触器故障";
                } else {
                    errMsg = errMsg+"---"+"接触器故障";
                }
                back = true;
            }
            if (this.isErrOther8()) {
                if (!back){
                    errMsg = "顶升电机接触器故障";
                } else {
                    errMsg = errMsg+"---"+"顶升电机接触器故障";
                }
                back = true;
            }
            if (back){
                return errMsg;
            }
        }
        return errorDev;
    public int getErrorDev$(){
        if (errOther1){
            return 1;
        }
        if (errOther2){
            return 2;
        }
        if (errOther3){
            return 3;
        }
        if (errOther4){
            return 4;
        }
        if (errOther5){
            return 5;
        }
        if (errOther6){
            return 6;
        }
        if (errOther7){
            return 7;
        }
        return 0;
    }
    public java.util.List<java.util.Map<String, Object>> getExceptions() {
        java.util.List<java.util.Map<String, Object>> list = new java.util.ArrayList<>();
        if (errOther1) list.add(createException(0, "电路保护器断开"));
        if (errOther2) list.add(createException(1, "光电异常"));
        if (errOther3) list.add(createException(2, "运行超时"));
        if (errOther4) list.add(createException(3, "占位超时"));
        if (errOther5) list.add(createException(4, "有任务无货故障"));
        if (errOther6) list.add(createException(5, "变频器故障"));
        if (errOther7) list.add(createException(6, "接触器故障"));
        if (errOther8) list.add(createException(7, "顶升电机接触器故障"));
        return list;
    }
    private java.util.Map<String, Object> createException(int code, String msg) {
        java.util.Map<String, Object> map = new java.util.HashMap<>();
        map.put("code", code);
        map.put("msg", msg);
        return map;
    }
//    public Integer getNearbySta() {
//        if (getNearbySta == null) return 0;