| | |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.zy.asrs.entity.*; |
| | | import com.zy.asrs.entity.mes.TransArrivalStation; |
| | | import com.zy.asrs.entity.mes.TransInOutStationAllow; |
| | | import com.zy.asrs.entity.mes.TransParent; |
| | | import com.zy.asrs.entity.rcs.*; |
| | | import com.zy.asrs.enums.RcsRetMethodEnum; |
| | | import com.zy.asrs.mapper.BasDevpMapper; |
| | | import com.zy.asrs.mapper.BlockStationMapper; |
| | | import com.zy.asrs.mapper.BlockTaskMapper; |
| | | import com.zy.asrs.service.*; |
| | | import com.zy.common.utils.HttpHandler; |
| | | import com.zy.common.utils.RedisUtil; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.scheduling.annotation.Scheduled; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import javax.annotation.Resource; |
| | |
| | | import java.net.URLConnection; |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.util.*; |
| | | import java.util.regex.Matcher; |
| | | import java.util.regex.Pattern; |
| | | |
| | | @Slf4j |
| | | @Service |
| | | public class RcsServiceImpl implements RcsService { |
| | | |
| | | @Value("${wms.address}") |
| | | private String WMS_ADDRESS; |
| | | @Value("${personIn.url}") |
| | | private String PERSON_URL; |
| | | // 海康RCS地址 |
| | | @Value("${hik.url}") |
| | | private String HIK_URL; |
| | |
| | | @Resource |
| | | private WrkMastService wrkMastService; |
| | | |
| | | @Autowired |
| | | private RedisUtil redisUtil; |
| | | @Resource |
| | | private ApiLogService apiLogService; |
| | | |
| | | private static final String IS_START_CHECK_INTRUSION = "intrusion:check"; |
| | | private static final String IS_PERSON_INTRUSION = "intrusion:person"; |
| | | private static final String LAST_INTRUSION_TIME = "intrusion:lastTime"; |
| | | private static final String IS_BLOCK_AREA = "intrusion:block"; |
| | | |
| | | |
| | | // region 封锁区逻辑,目前只有一个大封锁区,任务全部转到滑块库处理,或直接写到滑块库 |
| | |
| | | */ |
| | | public void managerBlock() { |
| | | |
| | | try { |
| | | BlockTask firstTask = blockTaskMapper.findTop(); |
| | | if (firstTask == null) { |
| | | return; |
| | | } |
| | | EntityWrapper<BlockStation> wrapper = new EntityWrapper<>(); |
| | | wrapper.eq("block_no", firstTask.getBlockNo()); |
| | | List<BlockStation> stations = blockStationMapper.selectList(wrapper); |
| | | if (!stations.isEmpty()) { |
| | | boolean locked = false; |
| | | for (BlockStation station : stations) { |
| | | // 只允许1个厂家设备进入封锁区,status状态:0 空闲;1 海康封锁中;2 华晓封锁中;-1 异常; |
| | | if (station.getStatus() > 0 && !station.getStatus().equals(firstTask.getAgvFactory())) { |
| | | locked = true; |
| | | break; |
| | | } |
| | | } |
| | | try { |
| | | BlockTask firstTask = blockTaskMapper.findTop(); |
| | | if (firstTask == null) { |
| | | return; |
| | | } |
| | | EntityWrapper<BlockStation> wrapper = new EntityWrapper<>(); |
| | | wrapper.eq("block_no", firstTask.getBlockNo()); |
| | | List<BlockStation> stations = blockStationMapper.selectList(wrapper); |
| | | if (!stations.isEmpty()) { |
| | | boolean locked = false; |
| | | for (BlockStation station : stations) { |
| | | // 只允许1个厂家设备进入封锁区,status状态:0 空闲;1 海康封锁中;2 华晓封锁中;-1 异常; |
| | | if (station.getStatus() > 0 && !station.getStatus().equals(firstTask.getAgvFactory())) { |
| | | locked = true; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if (!locked) { |
| | | // 封锁状态 |
| | | int success = blockStationMapper.addByBlockNo(firstTask.getBlockNo(), firstTask.getAgvFactory()); |
| | | if (success > 0) { |
| | | // 通知RCS |
| | | RcsEqptNotify notify = new RcsEqptNotify(); |
| | | notify.setEqptCode(firstTask.getBlockNo()); |
| | | notify.setTaskCode(firstTask.getTaskCode()); |
| | | notify.setActionStatus("1"); |
| | | notifyEqpt(notify, firstTask.getAgvFactory()); |
| | | } |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("管理封锁区异常", e); |
| | | } |
| | | if (!locked) { |
| | | // 封锁状态 |
| | | int success = blockStationMapper.addByBlockNo(firstTask.getBlockNo(), firstTask.getAgvFactory()); |
| | | if (success > 0) { |
| | | // 通知RCS |
| | | RcsEqptNotify notify = new RcsEqptNotify(); |
| | | notify.setEqptCode(firstTask.getBlockNo()); |
| | | notify.setTaskCode(firstTask.getTaskCode()); |
| | | notify.setActionStatus("1"); |
| | | notifyEqpt(notify, firstTask.getAgvFactory()); |
| | | } |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("管理封锁区异常", e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | return 0; |
| | | } |
| | | |
| | | @Resource |
| | | private BasDevpMapper basDevpMapper; |
| | | |
| | | /** |
| | | * 2.2.1任务执行回馈 |
| | | * 厂家:海量、华晓 |
| | |
| | | // JSONObject taskMemo = JSONObject.parseObject(task.getMemo()); |
| | | // mesService.outFeedbackByTuo(taskMemo.getString("OrderNo"), task); |
| | | } break; |
| | | case APPLY_PUT: { // 放货申请 |
| | | String staNo = task.getStaNo(); |
| | | BasDevp basDevp = basDevpMapper.selectById(staNo); |
| | | if(basDevp.getAutoing().equals("Y") && basDevp.getLoading().equals("N") && basDevp.getWrkNo() == 0) { |
| | | |
| | | // 205 触发条码扫描 |
| | | if (staNo.equals("205")) { |
| | | Map<String,Object> params = new HashMap<>(); |
| | | params.put("siteId",staNo); |
| | | String response = new HttpHandler.Builder() |
| | | .setUri(WCS_URL) |
| | | .setPath("/site/startScan") |
| | | .setParams(params) |
| | | .build() |
| | | .doPost(); |
| | | log.info("{}放货申请给wcs下发条码扫描原始返回:{}",staNo,response); |
| | | } |
| | | |
| | | // 满足放货条件,调用RCS任务继续执行 |
| | | RcsTaskContinue rcsTaskContinue = new RcsTaskContinue(); |
| | | rcsTaskContinue.setRobotTaskCode(robotTaskCode); |
| | | rcsTaskContinue.setTriggerType("TASK"); |
| | | rcsTaskContinue.setTriggerCode(robotTaskCode); |
| | | int success = continueTask(rcsTaskContinue, 1); |
| | | if(success != 1) { |
| | | rcsReturn.setCode("Err_RobotCodeNotMatch"); |
| | | rcsReturn.setMessage("继续执行失败"); |
| | | JSONObject data = new JSONObject(); |
| | | data.put("robotTaskCode", robotTaskCode); |
| | | rcsReturn.setData(data); |
| | | return rcsReturn; |
| | | } |
| | | }else { |
| | | log.warn("站点:{},不满足放货条件,自动:{},无物:{},任务号:{}",staNo,basDevp.getAutoing(),basDevp.getLoading(),basDevp.getWrkNo()); |
| | | rcsReturn.setCode("Err_RobotCodeNotMatch"); |
| | | rcsReturn.setMessage("站点不满足放货条件"); |
| | | JSONObject data = new JSONObject(); |
| | | data.put("robotTaskCode", robotTaskCode); |
| | | rcsReturn.setData(data); |
| | | return rcsReturn; |
| | | } |
| | | } break; |
| | | case APPLY_PICK: { // 取货申请 |
| | | String staNo = task.getSourceStaNo(); |
| | | BasDevp basDevp = basDevpMapper.selectById(staNo); |
| | | if(basDevp.getAutoing().equals("Y") && basDevp.getLoading().equals("Y") |
| | | && basDevp.getWrkNo() > 0 && basDevp.getWrkNo() <= 9990) { |
| | | // 满足放货条件,调用RCS任务继续执行 |
| | | RcsTaskContinue rcsTaskContinue = new RcsTaskContinue(); |
| | | rcsTaskContinue.setRobotTaskCode(robotTaskCode); |
| | | rcsTaskContinue.setTriggerType("TASK"); |
| | | rcsTaskContinue.setTriggerCode(robotTaskCode); |
| | | int success = continueTask(rcsTaskContinue, 1); |
| | | if(success != 1) { |
| | | rcsReturn.setCode("Err_RobotCodeNotMatch"); |
| | | rcsReturn.setMessage("继续执行失败"); |
| | | JSONObject data = new JSONObject(); |
| | | data.put("robotTaskCode", robotTaskCode); |
| | | rcsReturn.setData(data); |
| | | return rcsReturn; |
| | | } |
| | | }else { |
| | | log.warn("站点:{},不满足取货条件,自动:{},无物:{},任务号:{}",staNo,basDevp.getAutoing(),basDevp.getLoading(),basDevp.getWrkNo()); |
| | | rcsReturn.setCode("Err_RobotCodeNotMatch"); |
| | | rcsReturn.setMessage("站点不满足放货条件"); |
| | | JSONObject data = new JSONObject(); |
| | | data.put("robotTaskCode", robotTaskCode); |
| | | rcsReturn.setData(data); |
| | | return rcsReturn; |
| | | } |
| | | } break; |
| | | case PICK_COMPLETE: { // 取货完成 |
| | | String staNo = task.getSourceStaNo(); |
| | | |
| | | // 清除输送线任务号 |
| | | Map<String,Object> params = new HashMap<>(); |
| | | params.put("siteId",staNo); |
| | | params.put("workNo",0); |
| | | params.put("staNo", 0); |
| | | params.put("pakMk","Y"); |
| | | String response = new HttpHandler.Builder() |
| | | .setUri(WCS_URL) |
| | | .setPath("/site/detl/update") |
| | | .setParams(params) |
| | | .build() |
| | | .doPost(); |
| | | log.info("agv反馈pickComplete给wcs发命令:{},返回:{}",JSONObject.toJSONString(params),response); |
| | | // agv继续执行 |
| | | // TransInOutStationAllow inOutStationAllow = new TransInOutStationAllow(); |
| | | // inOutStationAllow.setTaskno(robotTaskCode); |
| | | // inOutStationAllow.setStatus("Y"); |
| | | // inOutStationAllow.setAgvCode("agv001"); |
| | | // mesService.allowOutStation(inOutStationAllow); |
| | | } break; |
| | | case TASK_END: { |
| | | // 更新任务状态等内部逻辑 |
| | | task.setWrkSts(304L); // 301 任务下发、302 任务执行、303 任务中断、304 任务结束 |
| | |
| | | task.setModiUser(defaultUserId); |
| | | taskService.updateById(task); |
| | | // 任务完成 |
| | | mesService.reporterTask(rcsReporterTask); |
| | | // mesService.reporterTask(rcsReporterTask); |
| | | |
| | | // 入立库时,区分是空托还是满托,给输送线下发命令9990 空,9995满 |
| | | // 侧面205 9996空,9997满 |
| | | String transType = memo.getString("TransType"); |
| | | if("02".equals(transType) || "04".equals(transType)) { |
| | | int wrkNo = 9995; |
| | |
| | | } |
| | | } |
| | | int staNo = Integer.parseInt(task.getStaNo()); |
| | | if(staNo == 205) { // 侧面任务号转换 |
| | | wrkNo = wrkNo == 9990 ? 9996 : 9997; |
| | | } |
| | | Map<String,Object> params = new HashMap<>(); |
| | | params.put("siteId",staNo); |
| | | params.put("workNo",wrkNo); |
| | | params.put("staNo", staNo == 205 ? 205 : (staNo-1) ); |
| | | params.put("String","Y"); |
| | | params.put("pakMk","Y"); |
| | | String response = new HttpHandler.Builder() |
| | | .setUri(WCS_URL) |
| | | .setPath("/site/detl/update") |
| | |
| | | } else { |
| | | apply.setStationId(task.getStaNo()); |
| | | } |
| | | |
| | | if (RcsRetMethodEnum.APPLY_IN_STATION.getCode().equals(method)) { |
| | | JSONObject personRequest = new JSONObject(); |
| | | personRequest.put("TaskType", 2); |
| | | personRequest.put("callback", WMS_ADDRESS+"/api/robot/personIn"); |
| | | List<String> areaCodes = new ArrayList<>(Arrays.asList("03-H01", "03-H02", "03-M01")); |
| | | int i = 0; |
| | | for (String areaCode : areaCodes){ |
| | | personRequest.put("AreaCode", areaCode); |
| | | int j = PersonRequest(personRequest, "IN"); |
| | | if (j == 0){ |
| | | log.error("人员入侵系统调用失败"); |
| | | } |
| | | } |
| | | redisUtil.set(IS_START_CHECK_INTRUSION, "T"); |
| | | // 延迟处理,确保人员入侵系统信号优先处理 |
| | | try { |
| | | Thread.sleep(10000); // 睡眠10秒 |
| | | } catch (InterruptedException e) { |
| | | Thread.currentThread().interrupt(); |
| | | } |
| | | mesService.applyInStation(apply); |
| | | } else if (RcsRetMethodEnum.APPLY_OFF_STATION.getCode().equals(method)) { |
| | | mesService.applyOutStation(apply); |
| | | } else if (RcsRetMethodEnum.ARRIVE_OFF_STATION.getCode().equals(method)) { |
| | | JSONObject personRequest = new JSONObject(); |
| | | personRequest.put("TaskType", 2); |
| | | personRequest.put("callback", WMS_ADDRESS+"/api/robot/personIn"); |
| | | List<String> areaCodes = new ArrayList<>(Arrays.asList("03-H01", "03-H02", "03-M01")); |
| | | int i = 0; |
| | | for (String areaCode:areaCodes){ |
| | | personRequest.put("AreaCode", areaCode); |
| | | int j = PersonRequest(personRequest, "OUT"); |
| | | if (j == 0){ |
| | | log.error("人员入侵系统调用失败"); |
| | | } |
| | | } |
| | | redisUtil.set(IS_START_CHECK_INTRUSION, "F"); |
| | | |
| | | mesService.outStation(apply); |
| | | // agv继续执行 |
| | | |
| | | TransInOutStationAllow inOutStationAllow = new TransInOutStationAllow(); |
| | | inOutStationAllow.setTaskno(robotTaskCode); |
| | | inOutStationAllow.setStatus("Y"); |
| | | inOutStationAllow.setAgvCode("agv001"); |
| | | mesService.allowOutStation(inOutStationAllow); |
| | | // TransInOutStationAllow inOutStationAllow = new TransInOutStationAllow(); |
| | | // inOutStationAllow.setTaskno(robotTaskCode); |
| | | // inOutStationAllow.setStatus("Y"); |
| | | // inOutStationAllow.setAgvCode("agv001"); |
| | | // mesService.allowOutStation(inOutStationAllow); |
| | | } |
| | | } break; |
| | | case ARRIVE_ON_STATION: { |
| | |
| | | TransArrivalStation arrivalStation = new TransArrivalStation(); |
| | | arrivalStation.setTaskno(robotTaskCode); |
| | | arrivalStation.setTaskname(memo.getString("taskName")); |
| | | arrivalStation.setTuoPanId(taskDetl == null ? "":taskDetl.getZpallet()); // memo.getString("TuoPanId") |
| | | arrivalStation.setTuoPanId(task.getBarcode()); // memo.getString("TuoPanId") |
| | | arrivalStation.setProductLineId(memo.getString("ProductLineId")); |
| | | String transType = memo.getString("TransType"); |
| | | arrivalStation.setDaotype(transType); |
| | |
| | | return result.toString(); |
| | | } |
| | | |
| | | @Override |
| | | public RcsReturn siteBind(SiteBind siteBind) { |
| | | RcsReturn rcsReturn = new RcsReturn(); |
| | | String url = HIK_URL + "api/robot/controller/site/bind"; |
| | | String response = sendPost(url, JSONObject.toJSONString(siteBind)); |
| | | if (!StringUtils.isEmpty(response) && response.contains("code")){ |
| | | rcsReturn = JSONObject.parseObject(response, RcsReturn.class); |
| | | } else { |
| | | rcsReturn.setCode("ERROR"); |
| | | rcsReturn.setMessage("调用绑定接口RCS无返回"); |
| | | } |
| | | return rcsReturn; |
| | | } |
| | | |
| | | int PersonRequest(JSONObject personRequest, String Type){ |
| | | String url; |
| | | if (Type.equals("IN")){ |
| | | url = "/detect/start"; |
| | | }else{ |
| | | url = "/detect/stop"; |
| | | } |
| | | String URL = PERSON_URL + url; |
| | | String blockResponse = RcsServiceImpl.sendPost(URL, JSONObject.toJSONString(personRequest)); |
| | | JSONObject jsonObject = JSON.parseObject(blockResponse); |
| | | if (!StringUtils.isEmpty(blockResponse) && (jsonObject.getInteger("code") == 200)) { |
| | | return 1; |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | @Scheduled(fixedDelay = 1000) |
| | | public void personOut(){ |
| | | Object lastTimeObj = redisUtil.get(LAST_INTRUSION_TIME); |
| | | if (lastTimeObj == null) { |
| | | return; // 没有记录,直接返回 |
| | | } |
| | | long lastTime = Long.parseLong(lastTimeObj.toString()); // 先转String再转long |
| | | long now = System.currentTimeMillis(); |
| | | long waitTime = now - lastTime; |
| | | //循环检测是否有超过10秒没有更新有人信号 |
| | | if (waitTime > 10000){ |
| | | JSONObject personReturn = new JSONObject(); |
| | | |
| | | String hik_blockUrl = "api/robot/controller/zone/blockade"; |
| | | String hik_pauseUrl = "api/robot/controller/zone/pause"; |
| | | |
| | | String BLOCK_URL = HIK_URL + hik_blockUrl; |
| | | String PAUSE_URL = HIK_URL + hik_pauseUrl; |
| | | |
| | | // 三个AGV区域 |
| | | List<String> areaCodes = new ArrayList<>(Arrays.asList("oprs1", "oprs2", "oprs3")); |
| | | |
| | | for (String areaCode:areaCodes){ |
| | | JSONObject rcsBlock = new JSONObject(); |
| | | JSONObject rcsPause = new JSONObject(); |
| | | rcsBlock.put("mapCode", "AA"); |
| | | rcsPause.put("mapCode", "AA"); |
| | | rcsBlock.put("invoke", "OPENUP"); |
| | | rcsPause.put("invoke","RUN"); |
| | | rcsBlock.put("zoneCode", areaCode); |
| | | rcsPause.put("zoneCode", areaCode); |
| | | |
| | | // 解除AGV锁定区域与解除暂停 |
| | | String blockResponse = RcsServiceImpl.sendPost(BLOCK_URL, JSONObject.toJSONString(rcsBlock)); |
| | | String PauseResponse = RcsServiceImpl.sendPost(PAUSE_URL, JSONObject.toJSONString(rcsPause)); |
| | | JSONObject blockJsonObject = JSON.parseObject(blockResponse); |
| | | JSONObject pauseJsonObject = JSON.parseObject(PauseResponse); |
| | | if (!StringUtils.isEmpty(blockResponse) && (blockJsonObject.getString("code").equals("SUCCESS"))) { |
| | | if (!StringUtils.isEmpty(PauseResponse) && (pauseJsonObject.getString("code").equals("SUCCESS"))) { |
| | | personReturn.put("code", 200); |
| | | personReturn.put("message", "success"); |
| | | } |
| | | } |
| | | } |
| | | //重置封锁状态 |
| | | redisUtil.set(IS_BLOCK_AREA, "F"); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | //人员入侵系统回调接口实现方法 |
| | | public int personIn(JSONObject param) { |
| | | |
| | | //人员入侵系统检测到有人 |
| | | if (param.getString("AlarmValue").equals("1")){ |
| | | long date = new Date().getTime(); |
| | | //重置redis计时 |
| | | redisUtil.set(LAST_INTRUSION_TIME, String.valueOf(date)); |
| | | |
| | | //如果已经封锁区域就直接返回,避免多次调用agv接口 |
| | | Object blockArea = redisUtil.get(IS_BLOCK_AREA); |
| | | if (blockArea != null && "T".equals(blockArea)) { |
| | | return 1; |
| | | } |
| | | |
| | | redisUtil.set(IS_PERSON_INTRUSION, "T"); |
| | | } |
| | | |
| | | JSONObject personReturn = new JSONObject(); |
| | | |
| | | String hik_blockUrl = "api/robot/controller/zone/blockade"; |
| | | String hik_pauseUrl = "api/robot/controller/zone/pause"; |
| | | |
| | | String BLOCK_URL = HIK_URL + hik_blockUrl; |
| | | String PAUSE_URL = HIK_URL + hik_pauseUrl; |
| | | |
| | | JSONObject rcsBlock = new JSONObject(); |
| | | JSONObject rcsPause = new JSONObject(); |
| | | rcsBlock.put("mapCode", "AA"); |
| | | rcsPause.put("mapCode", "AA"); |
| | | |
| | | List<String> areaCodes = new ArrayList<>(Arrays.asList("oprs1", "oprs2", "oprs3")); |
| | | |
| | | for (String areaCode:areaCodes){ |
| | | rcsBlock.put("zoneCode", areaCode); |
| | | rcsPause.put("zoneCode", areaCode); |
| | | rcsBlock.put("invoke", "BLOCKADE"); |
| | | rcsPause.put("invoke","FREEZE"); |
| | | String blockResponse = RcsServiceImpl.sendPost(BLOCK_URL, JSONObject.toJSONString(rcsBlock)); |
| | | String PauseResponse = RcsServiceImpl.sendPost(PAUSE_URL, JSONObject.toJSONString(rcsPause)); |
| | | JSONObject blockJsonObject = JSON.parseObject(blockResponse); |
| | | JSONObject pauseJsonObject = JSON.parseObject(PauseResponse); |
| | | if (!StringUtils.isEmpty(blockResponse) && (blockJsonObject.getString("code").equals("SUCCESS"))) { |
| | | if (!StringUtils.isEmpty(PauseResponse) && (pauseJsonObject.getString("code").equals("SUCCESS"))) { |
| | | personReturn.put("code", 200); |
| | | personReturn.put("message", "success"); |
| | | } |
| | | } |
| | | } |
| | | // 更新存储封锁信息 |
| | | redisUtil.set(IS_BLOCK_AREA, "T"); |
| | | //直接返回,不需要信息 |
| | | return 1; |
| | | } |
| | | // endregion |
| | | } |