package com.mes.md.service.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.mes.md.entity.RotatingRack;
|
import com.mes.md.mapper.RotatingRackMapper;
|
import com.mes.md.service.RotatingRackService;
|
import com.mes.utils.Result;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.core.ParameterizedTypeReference;
|
import org.springframework.http.*;
|
import org.springframework.stereotype.Service;
|
import org.springframework.util.StringUtils;
|
import org.springframework.web.client.HttpClientErrorException;
|
import org.springframework.web.client.RestTemplate;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.scheduling.annotation.Scheduled;
|
|
import java.nio.charset.StandardCharsets;
|
import java.util.*;
|
import java.util.stream.Collectors;
|
import java.text.ParseException;
|
import java.text.SimpleDateFormat;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
@Service
|
public class RotatingRackServiceImpl extends ServiceImpl<RotatingRackMapper, RotatingRack> implements RotatingRackService {
|
|
private static final Logger log = LoggerFactory.getLogger(RotatingRackServiceImpl.class);
|
private static final String BASE_API_URL = "http://10.3.58.110/api/Robot";
|
|
@Autowired
|
private RotatingRackMapper rotatingRackMapper;
|
|
@Autowired
|
private RestTemplate restTemplate;
|
|
@Override
|
public Result queryRackData(Map<String, String> params) {
|
try {
|
// 构建查询条件
|
LambdaQueryWrapper<RotatingRack> queryWrapper = new LambdaQueryWrapper<>();
|
|
// 根据日期范围查询
|
if (StringUtils.hasText(params.get("fromDate"))) {
|
// 将字符串转换为Date对象
|
try {
|
String dateStr = params.get("fromDate").trim();
|
Date fromDate;
|
if (dateStr.contains("T")) {
|
// 处理ISO 8601格式
|
SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
|
isoFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
|
fromDate = isoFormat.parse(dateStr);
|
} else {
|
// 处理普通格式
|
fromDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(dateStr);
|
}
|
queryWrapper.ge(RotatingRack::getStartDate, fromDate);
|
} catch (ParseException e) {
|
log.error("日期解析错误: {}", e.getMessage());
|
}
|
}
|
|
if (StringUtils.hasText(params.get("toDate"))) {
|
try {
|
String dateStr = params.get("toDate").trim();
|
Date toDate;
|
if (dateStr.contains("T")) {
|
// 处理ISO 8601格式
|
SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
|
isoFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
|
toDate = isoFormat.parse(dateStr);
|
} else {
|
// 处理普通格式
|
toDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(dateStr);
|
}
|
queryWrapper.le(RotatingRack::getEndDate, toDate);
|
} catch (ParseException e) {
|
log.error("日期解析错误: {}", e.getMessage());
|
}
|
}
|
|
// 根据机器人编号查询
|
if (StringUtils.hasText(params.get("Arm_No"))) {
|
queryWrapper.eq(RotatingRack::getRobotNo, params.get("Arm_No").trim());
|
}
|
|
// 根据交付订单号查询
|
if (StringUtils.hasText(params.get("DO_NO"))) {
|
queryWrapper.like(RotatingRack::getDoCode, params.get("DO_NO").trim());
|
}
|
|
// 只查询已完成的任务
|
queryWrapper.eq(RotatingRack::getTaskStatus, 2);
|
|
// 执行查询
|
List<RotatingRack> results = rotatingRackMapper.selectList(queryWrapper);
|
|
// 将实体转换为前端需要的数据格式
|
List<Map<String, Object>> data = new ArrayList<>();
|
for (RotatingRack rack : results) {
|
Map<String, Object> record = new HashMap<>();
|
record.put("ROBOT_NO", rack.getRobotNo());
|
//record.put("RACK_NAME", rack.getRackName()); // 料架名称
|
record.put("DO_Code", rack.getDoCode()); // DO编号
|
record.put("SKU_CODE", rack.getSkuCode()); // SKU编号
|
record.put("GlassWeight", rack.getGlassWeight() + "KG");
|
record.put("PCS", rack.getTargetPcs());
|
//record.put("GlassWidth", rack.getWidth());
|
//record.put("GlassHeight", rack.getHeight());
|
//record.put("GlassThickness", rack.getThickness());
|
SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
|
record.put("StartDateTime", isoFormat.format(rack.getStartDate()));
|
record.put("EndDateTime", isoFormat.format(rack.getEndDate()));
|
record.put("Broken", rack.getBroken());
|
record.put("SucessfullyCompleted", rack.getCompletedPcs()); // 成功完成数量
|
record.put("ElectricityConsume", rack.getElectricityConsume());
|
record.put("DownTime", rack.getDownTime());
|
record.put("Operator_Name", rack.getOperatorName());
|
data.add(record);
|
}
|
|
return Result.build(200, "Success", data);
|
} catch (Exception e) {
|
log.error("查询料架数据失败: {}", e.getMessage(), e);
|
return Result.build(500, "Error: " + e.getMessage(), null);
|
}
|
}
|
|
@Override
|
public Result searchDO(String searchKey) {
|
try {
|
if (!StringUtils.hasText(searchKey)) {
|
return Result.build(200, "Success", Collections.emptyList());
|
}
|
|
String url = BASE_API_URL + "/DOSearch?prefix=" + searchKey;
|
|
try {
|
log.info("发送DO搜索请求...");
|
ResponseEntity<List<Map<String, Object>>> response = restTemplate.exchange(
|
url,
|
HttpMethod.GET,
|
null,
|
new ParameterizedTypeReference<List<Map<String, Object>>>() {}
|
);
|
|
if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
|
return Result.build(200, "Success", response.getBody());
|
} else {
|
log.warn("搜索DO返回空结果或非200状态码: {}", response.getStatusCode());
|
return Result.build(200, "Success", Collections.emptyList());
|
}
|
} catch (Exception e) {
|
log.error("调用DO搜索API失败: {}", e.getMessage(), e);
|
return Result.build(500, "调用DO搜索API失败: " + e.getMessage(), null);
|
}
|
} catch (Exception e) {
|
log.error("搜索DO失败: {}", e.getMessage(), e);
|
return Result.build(500, "Error: " + e.getMessage(), null);
|
}
|
}
|
|
@Override
|
public Result searchSKU(String searchKey) {
|
try {
|
if (!StringUtils.hasText(searchKey)) {
|
return Result.build(200, "Success", Collections.emptyList());
|
}
|
|
String url = BASE_API_URL + "/FGSearch?prefix=" + searchKey;
|
|
try {
|
log.info("发送SKU搜索请求...");
|
ResponseEntity<List<Map<String, Object>>> response = restTemplate.exchange(
|
url,
|
HttpMethod.GET,
|
null,
|
new ParameterizedTypeReference<List<Map<String, Object>>>() {}
|
);
|
|
if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
|
return Result.build(200, "Success", response.getBody());
|
} else {
|
log.warn("搜索SKU返回空结果或非200状态码: {}", response.getStatusCode());
|
return Result.build(200, "Success", Collections.emptyList());
|
}
|
} catch (Exception e) {
|
log.error("调用SKU搜索API失败: {}", e.getMessage(), e);
|
return Result.build(500, "调用SKU搜索API失败: " + e.getMessage(), null);
|
}
|
} catch (Exception e) {
|
log.error("搜索SKU失败: {}", e.getMessage(), e);
|
return Result.build(500, "Error: " + e.getMessage(), null);
|
}
|
}
|
|
@Override
|
public Long startTask(RotatingRack rotatingRack) {
|
|
|
// 直接返回,不保存到数据库
|
return rotatingRack.getId();
|
}
|
|
@Override
|
public boolean completeTask(RotatingRack rotatingRack) {
|
try {
|
// 获取原任务信息并更新完成信息
|
rotatingRack.setEndDate(new Date());
|
rotatingRack.setTaskStatus(2); // 已完成
|
rotatingRack.setDownTime(0);
|
|
// 计算电力消耗:功率(12kW) * 运行时间(小时)
|
long durationMs = rotatingRack.getEndDate().getTime() - rotatingRack.getStartDate().getTime();
|
double durationHours = durationMs / (1000.0 * 60 * 60); // 转换为小时
|
double electricityConsume = 12.0 * durationHours; // 12kW * 运行时间(小时)
|
// 保留两位小数
|
electricityConsume = Math.round(electricityConsume * 100.0) / 100.0;
|
rotatingRack.setElectricityConsume(electricityConsume);
|
|
rotatingRack.setErpSentStatus(0); // 初始化为未发送状态
|
|
// 计算破损数量 = 目标数量 - 完成数量
|
if (rotatingRack.getTargetPcs() != null && rotatingRack.getCompletedPcs() != null) {
|
rotatingRack.setBroken(rotatingRack.getTargetPcs() - rotatingRack.getCompletedPcs());
|
if (rotatingRack.getBroken() < 0) {
|
rotatingRack.setBroken(0);
|
}
|
}
|
|
// 计算玻璃重量(根据宽度、高度、厚度计算)
|
if (rotatingRack.getWidth() != null && rotatingRack.getHeight() != null && rotatingRack.getThickness() != null) {
|
// 玻璃密度约为2.5g/cm³
|
// 宽(cm) * 高(cm) * 厚(mm) / 10 = 体积(cm³)
|
double volume = rotatingRack.getWidth() * rotatingRack.getHeight() * rotatingRack.getThickness() / 10.0;
|
// 重量(kg) = 体积(cm³) * 密度(g/cm³) / 1000
|
double weight = volume * 2.5 / 1000.0;
|
// 保留两位小数
|
weight = Math.round(weight * 100.0) / 100.0;
|
rotatingRack.setGlassWeight(weight);
|
log.info("料架{}玻璃重量: {}kg", rotatingRack.getRobotNo(), weight);
|
}
|
|
log.info("完成目标数量: {}", rotatingRack.getCompletedPcs());
|
// 设置是否成功完成
|
rotatingRack.setSuccessfullyCompleted(
|
(rotatingRack.getBroken() != null && rotatingRack.getBroken() == 0) ? 1 : 0
|
);
|
|
// 准备发送到ERP的数据
|
Map<String, Object> erpData = new HashMap<>();
|
erpData.put("ROBOT_NO", rotatingRack.getRobotNo());
|
erpData.put("DO_Code", rotatingRack.getDoCode());
|
erpData.put("SKU_CODE", rotatingRack.getSkuCode());
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
|
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
|
erpData.put("StartDateTime", dateFormat.format(rotatingRack.getStartDate()));
|
erpData.put("EndDateTime", dateFormat.format(rotatingRack.getEndDate()));
|
erpData.put("PCS", String.valueOf(rotatingRack.getCompletedPcs())); // 转换为字符串
|
erpData.put("Broken", rotatingRack.getBroken() != null && rotatingRack.getBroken() > 0 ? "True" : "False");
|
erpData.put("SuccessfullyCompleted", rotatingRack.getSuccessfullyCompleted() == 1 ? "True" : "False");
|
erpData.put("GlassWeight", String.valueOf(rotatingRack.getGlassWeight()));
|
erpData.put("Oparator_Name", rotatingRack.getOperatorName());
|
erpData.put("ElectricityConsume", String.valueOf(rotatingRack.getElectricityConsume())); // 转为字符串
|
erpData.put("DownTime", rotatingRack.getDownTime() != null ? rotatingRack.getDownTime() : 0); // 保持整数类型
|
|
// 确保数据字段有效性,防止空值
|
if (erpData.get("Oparator_Name") == null) {
|
erpData.put("Oparator_Name", "TEST");
|
}
|
if (erpData.get("GlassWeight") == null) {
|
erpData.put("GlassWeight", "0");
|
}
|
if (erpData.get("ElectricityConsume") == null) {
|
erpData.put("ElectricityConsume", "0");
|
}
|
if (erpData.get("DownTime") == null) {
|
erpData.put("DownTime", 0);
|
}
|
|
// 记录发送的数据,帮助调试
|
log.info("准备发送数据到ERP:{}", erpData);
|
|
// 尝试发送数据到ERP
|
boolean erpSendSuccess = sendToERP(erpData);
|
|
if (!erpSendSuccess) {
|
// ERP发送失败,保存到本地数据库,并标记为发送失败
|
log.warn("发送数据到ERP失败,任务数据保存到数据库。任务ID: {}", rotatingRack.getId());
|
rotatingRack.setErpSentStatus(2); // 标记为发送失败
|
rotatingRackMapper.insert(rotatingRack);
|
return false;
|
}
|
|
// 发送成功,直接返回true,不保存到数据库
|
return true;
|
} catch (Exception e) {
|
log.error("完成任务处理失败: {}", e.getMessage(), e);
|
// 发生异常时保存到本地数据库
|
try {
|
rotatingRack.setErpSentStatus(2); // 标记为发送失败
|
rotatingRackMapper.insert(rotatingRack);
|
log.info("任务数据已保存到本地数据库。任务ID: {}", rotatingRack.getId());
|
} catch (Exception dbEx) {
|
log.error("保存到本地数据库也失败: {}", dbEx.getMessage(), dbEx);
|
}
|
return false;
|
}
|
}
|
|
/**
|
* 发送数据到ERP系统
|
* @param data 要发送的数据
|
* @return 是否发送成功
|
*/
|
private boolean sendToERP(Map<String, Object> data) {
|
try {
|
// 设置API地址
|
String erpUrl = "http://10.3.58.110/api/Robot/Insert";
|
|
|
// 使用ObjectMapper手动序列化JSON
|
ObjectMapper objectMapper = new ObjectMapper();
|
String jsonData = objectMapper.writeValueAsString(data);
|
|
// 设置请求头
|
HttpHeaders headers = new HttpHeaders();
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
|
// 创建请求实体 - 直接使用JSON字符串
|
HttpEntity<String> requestEntity = new HttpEntity<>(jsonData, headers);
|
|
// 记录发送的数据,帮助调试
|
//log.info("准备发送数据到ERP: {}", jsonData);
|
|
// 发送POST请求
|
ResponseEntity<String> response = restTemplate.postForEntity(erpUrl, requestEntity, String.class);
|
|
// 检查响应状态码
|
if (response.getStatusCode() == HttpStatus.OK) {
|
//log.info("数据成功发送到ERP,响应内容:{}", response.getBody());
|
return true;
|
} else {
|
log.error("ERP接口返回非成功状态码:{}, 响应内容: {}", response.getStatusCode(), response.getBody());
|
return false;
|
}
|
}catch (HttpClientErrorException e) {
|
try {
|
// 尝试按UTF-8解码响应体
|
String responseBody = new String(e.getResponseBodyAsByteArray(), StandardCharsets.UTF_8);
|
log.error("发送数据到ERP失败,HTTP错误: {}, 响应状态: {}, 响应内容: {}",
|
e.getMessage(), e.getStatusCode(), responseBody, e);
|
} catch (Exception ex) {
|
log.error("发送数据到ERP失败,HTTP错误: {}, 响应状态: {}",
|
e.getMessage(), e.getStatusCode(), e);
|
}
|
return false;
|
} catch (Exception e) {
|
log.error("发送数据到ERP失败,未知错误: {}", e.getMessage(), e);
|
return false;
|
}
|
}
|
|
/**
|
* 定时任务:每分钟检查一次未成功发送到ERP的数据,并尝试重新发送
|
*/
|
@Scheduled(fixedRate = 60000) // 1分钟
|
public void retryFailedErpSending() {
|
log.info("开始执行定时任务:重试发送失败的数据到ERP");
|
try {
|
// 查询所有发送失败的数据
|
LambdaQueryWrapper<RotatingRack> queryWrapper = new LambdaQueryWrapper<>();
|
queryWrapper.eq(RotatingRack::getErpSentStatus, 2); // 查询发送失败的数据
|
|
List<RotatingRack> failedRecords = rotatingRackMapper.selectList(queryWrapper);
|
|
if (failedRecords.isEmpty()) {
|
//log.info("没有需要重试发送的数据");
|
return;
|
}
|
|
log.info("找到{}条发送失败的数据,开始重试发送", failedRecords.size());
|
|
int successCount = 0;
|
int failCount = 0;
|
|
for (RotatingRack record : failedRecords) {
|
// 准备发送到ERP的数据
|
Map<String, Object> erpData = new HashMap<>();
|
erpData.put("ROBOT_NO", record.getRobotNo());
|
erpData.put("DO_Code", record.getDoCode());
|
erpData.put("SKU_CODE", record.getSkuCode());
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
|
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
|
erpData.put("StartDateTime", dateFormat.format(record.getStartDate()));
|
erpData.put("EndDateTime", dateFormat.format(record.getEndDate()));
|
erpData.put("PCS", String.valueOf(record.getCompletedPcs()));
|
erpData.put("Broken", record.getBroken() != null && record.getBroken() > 0 ? "True" : "False");
|
erpData.put("SuccessfullyCompleted", record.getSuccessfullyCompleted() == 1 ? "True" : "False");
|
erpData.put("GlassWeight", String.valueOf(record.getGlassWeight()));
|
erpData.put("Oparator_Name", record.getOperatorName());
|
erpData.put("ElectricityConsume", String.valueOf(record.getElectricityConsume())); // 转为字符串
|
erpData.put("DownTime", record.getDownTime() != null ? record.getDownTime() : 0); // 保持整数类型
|
|
// 确保数据字段有效性,防止空值
|
if (erpData.get("Oparator_Name") == null) {
|
erpData.put("Oparator_Name", "TEST");
|
}
|
if (erpData.get("GlassWeight") == null) {
|
erpData.put("GlassWeight", "0");
|
}
|
if (erpData.get("ElectricityConsume") == null) {
|
erpData.put("ElectricityConsume", "0");
|
}
|
if (erpData.get("DownTime") == null) {
|
erpData.put("DownTime", 0);
|
}
|
|
// 记录发送的数据
|
log.info("准备重试发送数据到ERP,任务ID: {}, 数据: {}", record.getId(), erpData);
|
|
// 尝试重新发送
|
boolean sendSuccess = sendToERP(erpData);
|
|
if (sendSuccess) {
|
// 发送成功,更新状态
|
record.setErpSentStatus(1);
|
rotatingRackMapper.updateById(record);
|
successCount++;
|
log.info("成功重试发送数据到ERP,任务ID: {}", record.getId());
|
} else {
|
failCount++;
|
log.warn("重试发送数据到ERP失败,任务ID: {}", record.getId());
|
}
|
}
|
|
log.info("定时任务执行完成,成功发送: {}条,失败: {}条", successCount, failCount);
|
} catch (Exception e) {
|
log.error("定时任务执行异常: {}", e.getMessage(), e);
|
}
|
}
|
}
|