|
|
@@ -0,0 +1,221 @@
|
|
|
+package com.github.zuihou.business.controller.externalApi;
|
|
|
+
|
|
|
+import cn.hutool.core.bean.BeanUtil;
|
|
|
+import cn.hutool.core.date.DatePattern;
|
|
|
+import cn.hutool.core.date.DateUtil;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.github.zuihou.authority.service.common.ParameterService;
|
|
|
+import com.github.zuihou.base.R;
|
|
|
+import com.github.zuihou.business.externalApi.entity.AgvHikOrderDetailInfo;
|
|
|
+import com.github.zuihou.business.externalApi.entity.AgvHikOrderInfo;
|
|
|
+import com.github.zuihou.business.externalApi.entity.AgvOrderDetailInfo;
|
|
|
+import com.github.zuihou.business.externalApi.entity.AgvOrderInfo;
|
|
|
+import com.github.zuihou.business.externalApi.service.*;
|
|
|
+import com.github.zuihou.common.constant.HikR;
|
|
|
+import com.github.zuihou.common.constant.ParameterKey;
|
|
|
+import com.github.zuihou.common.enums.AgvActionEnum;
|
|
|
+import com.github.zuihou.common.enums.AgvLocationRelationEnum;
|
|
|
+import com.github.zuihou.common.util.StringUtil;
|
|
|
+import com.github.zuihou.context.BaseContextHandler;
|
|
|
+import com.github.zuihou.database.mybatis.conditions.query.LbqWrapper;
|
|
|
+import com.github.zuihou.log.annotation.SysLog;
|
|
|
+import io.swagger.annotations.Api;
|
|
|
+import io.swagger.annotations.ApiOperation;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.data.redis.core.RedisTemplate;
|
|
|
+import org.springframework.http.HttpEntity;
|
|
|
+import org.springframework.http.HttpHeaders;
|
|
|
+import org.springframework.http.MediaType;
|
|
|
+import org.springframework.validation.annotation.Validated;
|
|
|
+import org.springframework.web.bind.annotation.PostMapping;
|
|
|
+import org.springframework.web.bind.annotation.RequestBody;
|
|
|
+import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
+import org.springframework.web.bind.annotation.RestController;
|
|
|
+import org.springframework.web.client.RestTemplate;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.Calendar;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+/**
|
|
|
+ * <p>
|
|
|
+ * 前端控制器
|
|
|
+ * agv交互
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * @author imcs
|
|
|
+ * @date 2021-07-09
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Validated
|
|
|
+@RestController
|
|
|
+@RequestMapping("/agv/agvCallbackService")
|
|
|
+@Api(value = "AgvInfo", tags = "agv交互")
|
|
|
+@SysLog(enabled = true)
|
|
|
+public class HikAgvControl {
|
|
|
+ @Autowired
|
|
|
+ private RedisTemplate<String,Object> redisTemplate;
|
|
|
+ @Resource
|
|
|
+ private RestTemplate restTemplate;
|
|
|
+ @Autowired
|
|
|
+ private ParameterService parameterService;
|
|
|
+ @Autowired
|
|
|
+ private AgvHikOrderDetailInfoService agvHikOrderDetailInfoService;
|
|
|
+ @Autowired
|
|
|
+ private AgvHikOrderInfoService agvHikOrderInfoService;
|
|
|
+ @Autowired
|
|
|
+ private ExternalApiService externalApiService;
|
|
|
+
|
|
|
+ @ApiOperation(value = "agv任务完成回调", notes = "agv任务完成回调")
|
|
|
+ @PostMapping("/agvCallback")
|
|
|
+ public HikR agvCallback(@RequestBody Map<String, String> data) {
|
|
|
+ log.info("接收到agv任务回调,参数是{}", data.toString());
|
|
|
+ BaseContextHandler.setTenant("0000");
|
|
|
+ // 判断回调内容是否正确
|
|
|
+ // agv 任务id
|
|
|
+ String taskCode = null == data.get("taskCode") ? "":data.get("taskCode");
|
|
|
+ String code = null == data.get("code") ? "":data.get("code");
|
|
|
+ String msg = null == data.get("msg") ? "":data.get("msg");
|
|
|
+ if(StringUtil.isEmpty(taskCode)){
|
|
|
+ return HikR.fail("任务单号为空");
|
|
|
+ }
|
|
|
+ if(StringUtil.isEmpty(code)){
|
|
|
+ return HikR.fail("任务状态码为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ LbqWrapper<AgvHikOrderDetailInfo> wrapper = new LbqWrapper<>();
|
|
|
+ wrapper.eq(AgvHikOrderDetailInfo::getTaskCode, Integer.valueOf(taskCode));
|
|
|
+ AgvHikOrderDetailInfo agvHikOrderDetailInfo = agvHikOrderDetailInfoService.getOne(wrapper);
|
|
|
+ if(null != agvHikOrderDetailInfo){
|
|
|
+ AgvHikOrderDetailInfo callbackInfo = JSONObject.parseObject(JSONObject.toJSONString(data),AgvHikOrderDetailInfo.class);
|
|
|
+ BeanUtil.copyProperties(agvHikOrderDetailInfo,callbackInfo);
|
|
|
+ agvHikOrderDetailInfoService.updateAllById(agvHikOrderDetailInfo);
|
|
|
+// return R.success();
|
|
|
+ }else{
|
|
|
+ return HikR.fail("agv任务不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ LbqWrapper<AgvHikOrderInfo> agvHikOrderInfoWrapper = new LbqWrapper<AgvHikOrderInfo>();
|
|
|
+ agvHikOrderInfoWrapper.eq(AgvHikOrderInfo::getAgvTaskId, Integer.valueOf(taskCode));
|
|
|
+ AgvHikOrderInfo agvHikOrderInfo = agvHikOrderInfoService.getOne(agvHikOrderInfoWrapper);
|
|
|
+
|
|
|
+ if("0".equals(code)){
|
|
|
+// redisTemplate.opsForValue().set("agvOkFlag",true);
|
|
|
+ // 读取PLC托板是否放平信号
|
|
|
+ // TODO 待修改
|
|
|
+ Object agvOkObj = redisTemplate.opsForValue().get("agvOkFlag");
|
|
|
+ Boolean agvOkFlag =(agvOkObj==null?true:(Boolean)agvOkObj);
|
|
|
+
|
|
|
+// Object nodeId = redisTemplate.opsForValue().get(taskId);
|
|
|
+// String taskNodeId =(nodeId==null?"":nodeId.toString()) ;
|
|
|
+// String[] taskNodes = taskNodeId.split("-");
|
|
|
+// if(StringUtil.isEmpty(taskNodeId)){
|
|
|
+// return R.fail("任务不存在");
|
|
|
+// }
|
|
|
+ // 托板已经到位
|
|
|
+ Object autoNodeTaskInfo = redisTemplate.opsForValue().get(taskCode);
|
|
|
+ JSONObject autoNodeTaskInfoObj =(autoNodeTaskInfo==null?null:JSONObject.parseObject(autoNodeTaskInfo.toString()));
|
|
|
+
|
|
|
+ if(agvOkFlag){
|
|
|
+ redisTemplate.delete(taskCode);
|
|
|
+ // TODO 记录AGV相关流程日志信息
|
|
|
+ // 指令下发出库完成后回调调度完成后续任务
|
|
|
+ // 从redis里面获取上次出库任务 任务号-任务结点号
|
|
|
+// return R.success();
|
|
|
+
|
|
|
+ autoNodeTaskInfoObj.put("code","1");
|
|
|
+ HttpHeaders headers = new HttpHeaders();
|
|
|
+ headers.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
|
|
|
+
|
|
|
+ HttpEntity<String> formEntity = new HttpEntity<String>(autoNodeTaskInfoObj.toJSONString(),headers);
|
|
|
+ String taskNodeCallbackUrl = parameterService.getValue(ParameterKey.TASKNODECALLBACKURL, null);
|
|
|
+ int sendCount = 0;
|
|
|
+ // 解析回调结果
|
|
|
+ boolean flag = repeatSend(taskNodeCallbackUrl,formEntity,sendCount);
|
|
|
+ if(flag){
|
|
|
+ return HikR.success().setReqCode(agvHikOrderDetailInfo.getReqCode());
|
|
|
+ }else{
|
|
|
+ // TODO 记录告警日志方便电子看板或者其他地方展示系统通讯异常
|
|
|
+ return HikR.success().setReqCode(agvHikOrderDetailInfo.getReqCode());
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ // 托板未到位需重新驱动agv托起托板再次放
|
|
|
+ // 异步唤醒
|
|
|
+ // 查询到上一次任务的重点,发agv重新托起在放
|
|
|
+ if(0 == agvHikOrderInfo.getRepeatActionType()){
|
|
|
+ String goal = "";
|
|
|
+ for (AgvLocationRelationEnum agvLocationRelationEnum : AgvLocationRelationEnum.values()) {
|
|
|
+ if (agvLocationRelationEnum.getPreserveLocation().equals(agvHikOrderInfo.getGoal())){
|
|
|
+ goal = agvLocationRelationEnum.getSafeLocation();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ externalApiService.addAgvTask(agvHikOrderInfo.getGoal(), AgvActionEnum.SITUANDUP.getActionId(), goal,0, agvHikOrderInfo.getTaskId(), agvHikOrderInfo.getTaskNodeId(), Integer.valueOf(taskCode),1);
|
|
|
+ }else if(1 == agvHikOrderInfo.getRepeatActionType()){
|
|
|
+
|
|
|
+ String goal = "";
|
|
|
+ for (AgvLocationRelationEnum agvLocationRelationEnum : AgvLocationRelationEnum.values()) {
|
|
|
+ if (agvLocationRelationEnum.getSafeLocation().equals(agvHikOrderInfo.getGoal())){
|
|
|
+ goal = agvLocationRelationEnum.getPreserveLocation();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ externalApiService.addAgvTask(agvHikOrderInfo.getGoal(), 0, goal, AgvActionEnum.SITUANDDOWN.getActionId(), agvHikOrderInfo.getTaskId(), agvHikOrderInfo.getTaskNodeId(), agvHikOrderInfo.getParentAgvTaskId(),2);
|
|
|
+ }
|
|
|
+ redisTemplate.delete(taskCode);
|
|
|
+ return HikR.success().setReqCode(agvHikOrderDetailInfo.getReqCode());
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ // TODO 记录AGV任务异常信息并告警
|
|
|
+ Object autoNodeTaskInfo = redisTemplate.opsForValue().get(taskCode);
|
|
|
+ JSONObject autoNodeTaskInfoObj =(autoNodeTaskInfo==null?null:JSONObject.parseObject(autoNodeTaskInfo.toString()));
|
|
|
+ redisTemplate.delete(taskCode);
|
|
|
+ // TODO 后续改成0失败
|
|
|
+ autoNodeTaskInfoObj.put("code","1");
|
|
|
+ HttpHeaders headers = new HttpHeaders();
|
|
|
+ headers.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
|
|
|
+
|
|
|
+ HttpEntity<String> formEntity = new HttpEntity<String>(autoNodeTaskInfoObj.toJSONString(),headers);
|
|
|
+ String taskNodeCallbackUrl = parameterService.getValue(ParameterKey.TASKNODECALLBACKURL, null);
|
|
|
+ int sendCount = 0;
|
|
|
+ // 解析回调结果
|
|
|
+ boolean flag = repeatSend(taskNodeCallbackUrl,formEntity,sendCount);
|
|
|
+ if(flag){
|
|
|
+ return HikR.success().setReqCode(agvHikOrderDetailInfo.getReqCode());
|
|
|
+ }else{
|
|
|
+ // TODO 记录告警日志方便电子看板或者其他地方展示系统通讯异常
|
|
|
+ return HikR.success().setReqCode(agvHikOrderDetailInfo.getReqCode());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 回调任务是否完成
|
|
|
+ * @param taskNodeCallbackUrl
|
|
|
+ * @param formEntity
|
|
|
+ * @param sendCount
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private boolean repeatSend(String taskNodeCallbackUrl, HttpEntity<String> formEntity, int sendCount){
|
|
|
+ sendCount ++;
|
|
|
+ Boolean flag = false;
|
|
|
+ log.info("agv taskNode callback request = {}",formEntity.getBody().toString());
|
|
|
+ String returnData = restTemplate.postForObject(taskNodeCallbackUrl,formEntity, String.class);
|
|
|
+ log.info("agv taskNode callback response = {}",returnData);
|
|
|
+ JSONObject jsonObject = JSONObject.parseObject(returnData);
|
|
|
+ String code = jsonObject.getString("code");
|
|
|
+ // 回调成功
|
|
|
+ if("0".equals(code)){
|
|
|
+ flag = true;
|
|
|
+ return flag;
|
|
|
+ }else{
|
|
|
+ // 失败重发
|
|
|
+ if(!flag && sendCount < 3){
|
|
|
+ repeatSend(taskNodeCallbackUrl,formEntity,sendCount);
|
|
|
+ }else{
|
|
|
+ return flag;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return flag;
|
|
|
+ }
|
|
|
+}
|