feat():跟踪逻辑调整
This commit is contained in:
@@ -1,33 +1,36 @@
|
||||
package com.fizz.business.constants.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
/**
|
||||
* 细粒度设备枚举(按你给出的17台设备)
|
||||
* position 为基准位置(单位:m),用于和 stripLocation 比较。
|
||||
* paramFields 列出该设备需要采样/缓存的字段名(与 AppMeasure*Message 中字段名对应)。
|
||||
* 细粒度设备枚举
|
||||
* - position: 基准位置(单位:m)
|
||||
* - sectionType: 所属段(入口 / 工艺 / 出口)
|
||||
* - sourceType: 数据来源(ENTRY/FURNACE/COAT/EXIT)
|
||||
* - paramFields: 对应AppMeasure*Message中的字段
|
||||
*/
|
||||
@Getter
|
||||
public enum DeviceEnum {
|
||||
POR1(0, "1#开卷机", 0.0, Arrays.asList("tensionPorBr1", "stripSpeed")),
|
||||
POR2(1, "2#开卷机", 0.0, Arrays.asList("tensionPorBr2", "stripSpeed")),
|
||||
WELDER(2, "焊机", 16.433, Arrays.asList("weldStatus")),
|
||||
ENL1(3, "入口活套1", 58.987, Arrays.asList("celLength", "celCapacity", "tensionCel")),
|
||||
ENL2(4, "入口活套2", 118.518, Arrays.asList("celLength", "celCapacity", "tensionCel")),
|
||||
CLEAN(5, "清洗段", 97.607, Arrays.asList("cleaningVoltage", "cleaningCurrent", "alkaliConcentration", "alkaliTemperature")),
|
||||
FUR1(6, "退火炉-预热段", 63.013, Arrays.asList("phfExitStripTemp","potTemperature","gasConsumption")),
|
||||
FUR2(7, "退火炉-加热段", 72.01, Arrays.asList("rtfExitStripTemp","zincPotPower")),
|
||||
FUR3(8, "退火炉-冷却段", 30.71, Arrays.asList("jcsExitStripTemp","coolingTowerStripTemp")),
|
||||
FUR4(9, "退火炉-均衡段", 14.607, Arrays.asList("scsExitStripTemp")),
|
||||
POT(10, "锌锅", 10.373, Arrays.asList("scsExitStripTemp")),
|
||||
TOWER(11, "后处理", 144.412, Arrays.asList("scsExitStripTemp")),
|
||||
TM(11, "光整机", 26.527, Arrays.asList("tensionBr5Tm", "stripSpeedTmExit")),
|
||||
TL(12, "拉矫机", 15.027, Arrays.asList("tlElongation", "tensionTlBr7")),
|
||||
COAT(13, "后处理段", 145.5, Arrays.asList(
|
||||
// === 入口段 ===
|
||||
POR1(0, "1#开卷机", 0.0, SectionType.ENTRY, SourceType.ENTRY, Arrays.asList("tensionPorBr1", "stripSpeed")),
|
||||
POR2(1, "2#开卷机", 0.0, SectionType.ENTRY, SourceType.ENTRY, Arrays.asList("tensionPorBr2", "stripSpeed")),
|
||||
WELDER(2, "焊机", 16.433, SectionType.ENTRY, SourceType.ENTRY, Arrays.asList("weldStatus")),
|
||||
ENL1(3, "入口活套1", 75.42, SectionType.PROCESS, SourceType.ENTRY, Arrays.asList("celLength", "celCapacity", "tensionCel")),
|
||||
ENL2(4, "入口活套2", 193.94, SectionType.PROCESS, SourceType.ENTRY, Arrays.asList("celLength", "celCapacity", "tensionCel")),
|
||||
|
||||
// === 工艺段 ===
|
||||
CLEAN(5, "清洗段", 291.545, SectionType.PROCESS, SourceType.FURNACE, Arrays.asList("cleaningVoltage", "cleaningCurrent", "alkaliConcentration", "alkaliTemperature")),
|
||||
FUR1(6, "退火炉-预热段", 354.558, SectionType.PROCESS, SourceType.FURNACE, Arrays.asList("phfExitStripTemp", "potTemperature", "gasConsumption")),
|
||||
FUR2(7, "退火炉-加热段", 426.568, SectionType.PROCESS, SourceType.FURNACE, Arrays.asList("rtfExitStripTemp", "zincPotPower")),
|
||||
FUR3(8, "退火炉-冷却段", 457.278, SectionType.PROCESS, SourceType.FURNACE, Arrays.asList("jcsExitStripTemp", "coolingTowerStripTemp")),
|
||||
FUR4(9, "退火炉-均衡段", 471.885, SectionType.PROCESS, SourceType.FURNACE, Arrays.asList("scsExitStripTemp")),
|
||||
POT(10, "锌锅", 482.258, SectionType.PROCESS, SourceType.COAT, Arrays.asList("scsExitStripTemp")),
|
||||
TOWER(11, "冷却塔", 626.67, SectionType.PROCESS, SourceType.COAT, Arrays.asList("scsExitStripTemp")),
|
||||
TM(12, "光整机", 653.197, SectionType.PROCESS, SourceType.COAT, Arrays.asList("tensionBr5Tm", "stripSpeedTmExit")),
|
||||
TL(13, "拉矫机", 668.224, SectionType.PROCESS, SourceType.COAT, Arrays.asList("tlElongation", "tensionTlBr7")),
|
||||
COAT(14, "后处理段", 813.724, SectionType.PROCESS, SourceType.COAT, Arrays.asList(
|
||||
"avrCoatingWeightTop","stdCoatingWeightTop","maxCoatingWeightTop","minCoatingWeightTop",
|
||||
"avrCoatingWeightBottom","stdCoatingWeightBottom","maxCoatingWeightBottom","minCoatingWeightBottom",
|
||||
"airKnifePressure","airKnifeFlow","airKnifeGap","stripSpeedTmExit","tensionBr5Tm",
|
||||
@@ -36,21 +39,64 @@ public enum DeviceEnum {
|
||||
"tensionTlBr7","tensionBr6Br7","tlFlag","tlElongation","levelingUnit1Mesh","levelingUnit2Mesh",
|
||||
"antiCrossBowUnitMesh","tensionBr7Br8","stripSpeedAfp","stripTempAfp"
|
||||
)),
|
||||
CXL1(14, "出口活套1", 1, Arrays.asList("cxlLength", "cxlCapacity", "tensionCxl")),
|
||||
CXL2(15, "出口活套2", 126.837, Arrays.asList("cxlLength", "cxlCapacity", "tensionCxl")),
|
||||
INS(16, "检查站", 0, Arrays.asList("inspectionStatus")),
|
||||
TR(17, "卷取机", 21.549, Arrays.asList("coilLength", "speedExitSection", "tensionBr9Tr")),
|
||||
EXC(18, "卸卷小车", 999999.0, Collections.emptyList()),
|
||||
WEIGHT(19, "称重鞍座", 999999.0, Collections.emptyList());
|
||||
|
||||
// === 出口段 ===
|
||||
CXL1(15, "出口活套1", 900.561, SectionType.EXIT, SourceType.EXIT, Arrays.asList("cxlLength", "cxlCapacity", "tensionCxl")),
|
||||
CXL2(16, "出口活套2", 920.561, SectionType.EXIT, SourceType.EXIT, Arrays.asList("cxlLength", "cxlCapacity", "tensionCxl")),
|
||||
INS(17, "检查站", 940.561, SectionType.EXIT, SourceType.EXIT, Arrays.asList("inspectionStatus")),
|
||||
TR(18, "卷取机", 962.11, SectionType.EXIT, SourceType.EXIT, Arrays.asList("coilLength", "speedExitSection", "tensionBr9Tr")),
|
||||
EXC(19, "卸卷小车", 9999999.0, SectionType.EXIT, SourceType.EXIT, Collections.emptyList()),
|
||||
WEIGHT(20, "称重鞍座", 9999999.0, SectionType.EXIT, SourceType.EXIT, Collections.emptyList());
|
||||
|
||||
private final int idx;
|
||||
private final String desc;
|
||||
private final double basePosition;
|
||||
private final SectionType sectionType;
|
||||
private final SourceType sourceType;
|
||||
private final List<String> paramFields;
|
||||
|
||||
private static final Map<String, DeviceEnum> NAME_MAP = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (DeviceEnum d : values()) NAME_MAP.put(d.name(), d);
|
||||
}
|
||||
public static DeviceEnum fromName(String name) { return NAME_MAP.get(name); }
|
||||
|
||||
DeviceEnum(int idx, String desc, double basePosition, SectionType sectionType, SourceType sourceType, List<String> paramFields) {
|
||||
this.idx = idx;
|
||||
this.desc = desc;
|
||||
this.basePosition = basePosition;
|
||||
this.sectionType = sectionType;
|
||||
this.sourceType = sourceType;
|
||||
this.paramFields = paramFields;
|
||||
}
|
||||
|
||||
public static DeviceEnum fromName(String name) {
|
||||
return NAME_MAP.get(name);
|
||||
}
|
||||
|
||||
public boolean isEntrySection() {
|
||||
return sectionType == SectionType.ENTRY;
|
||||
}
|
||||
|
||||
public boolean isProcessSection() {
|
||||
return sectionType == SectionType.PROCESS;
|
||||
}
|
||||
|
||||
public boolean isExitSection() {
|
||||
return sectionType == SectionType.EXIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* 段类型:用于区分入口 / 工艺 / 出口
|
||||
*/
|
||||
public enum SectionType {
|
||||
ENTRY, PROCESS, EXIT
|
||||
}
|
||||
|
||||
/**
|
||||
* 来源类型:用于确定从哪个 AppMeasureXXXMessage 中取值
|
||||
*/
|
||||
public enum SourceType {
|
||||
ENTRY, FURNACE, COAT, EXIT
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,34 @@
|
||||
package com.fizz.business.service.hanle;
|
||||
|
||||
import com.fizz.business.anno.OpcMessageHandlerType;
|
||||
import com.fizz.business.constants.enums.DeviceEnum;
|
||||
import com.fizz.business.constants.enums.OpcMessageType;
|
||||
import com.fizz.business.domain.msg.*;
|
||||
import com.fizz.business.dto.MatmapDTO;
|
||||
import com.fizz.business.service.LogDataService;
|
||||
import com.fizz.business.service.OpcMessageHandler;
|
||||
import com.fizz.business.service.strip.SegmentTrackerService;
|
||||
import com.fizz.business.service.strip.StripPositionService;
|
||||
import com.fizz.business.utils.MatmapUtil;
|
||||
import com.fizz.business.utils.WebSocketUtil;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@Component
|
||||
@OpcMessageHandlerType(OpcMessageType.APP_MEASURE)
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class AppMeasureHandler implements OpcMessageHandler<AppMeasureMessage> {
|
||||
|
||||
private final SegmentTrackerService tracker;
|
||||
private final LogDataService logDataService;
|
||||
private final Executor coilTrackExecutor; // 注入线程池接口
|
||||
|
||||
private static final AtomicInteger LOG_COUNTER = new AtomicInteger(0);
|
||||
|
||||
@Override
|
||||
public void handle(AppMeasureMessage message) {
|
||||
@@ -31,15 +41,51 @@ public class AppMeasureHandler implements OpcMessageHandler<AppMeasureMessage> {
|
||||
|
||||
WebSocketUtil.sendMeasureMsg(message);
|
||||
|
||||
// 2) extract key fields
|
||||
String coilId = entry == null ? "UNKNOWN" : entry.getEntryCoilId();
|
||||
// 处理钢卷ID为空的情况
|
||||
String coilId ="";
|
||||
if (entry != null && entry.getEntryCoilId() != null){
|
||||
coilId = entry.getEntryCoilId();
|
||||
|
||||
}else {
|
||||
MatmapDTO matmapDTO =getCurrentRunningCoilId(entry);
|
||||
coilId = matmapDTO.getMatId();
|
||||
}
|
||||
|
||||
if (StringUtils.isEmpty(coilId) || "".equals(coilId)){
|
||||
log.error("钢卷号为空,无法执行焊缝跟踪!!!!!!");
|
||||
return;
|
||||
}
|
||||
|
||||
BigDecimal lengthAtWelder = entry == null || entry.getStripLocation() == null ? BigDecimal.ZERO : entry.getStripLocation();
|
||||
|
||||
// 3) delegate core processing to tracker
|
||||
// 每10次请求输出一次日志
|
||||
int count = LOG_COUNTER.incrementAndGet();
|
||||
if (count % 10 == 0) {
|
||||
logDataService.logInfo("WELDER",
|
||||
"接收到钢卷焊缝跟踪信号:当前焊缝长度 lengthAtWelder:{} 当前钢卷信息 coilId:{}",
|
||||
lengthAtWelder, coilId);
|
||||
}
|
||||
|
||||
// 核心逻辑处理
|
||||
tracker.handleMeasure(coilId, lengthAtWelder, entry, furnace, coat, exit);
|
||||
|
||||
// 调用新的方法来跟踪钢卷头部位置,并处理快照和 matmap 更新
|
||||
// 使用焊机长度作为最接近的钢卷头部位置
|
||||
tracker.trackCoilHeadPosition(coilId, lengthAtWelder, entry, exit);
|
||||
// 异步执行 trackCoilHeadPosition
|
||||
// coilTrackExecutor.execute(() -> {
|
||||
// try {
|
||||
// log.warn(">>> trackCoilHeadPosition start, thread: {}, coilId: {}",
|
||||
// Thread.currentThread().getName(), coilId);
|
||||
//
|
||||
// tracker.trackCoilHeadPosition(coilId, lengthAtWelder, entry, exit);
|
||||
//
|
||||
// } catch (Exception e) {
|
||||
// log.error("trackCoilHeadPosition 执行异常,coilId=" + coilId, e);
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
private MatmapDTO getCurrentRunningCoilId(AppMeasureEntryMessage entry) {
|
||||
|
||||
return MatmapUtil.getMatmap(entry.getPayOffReelNumber());
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.fizz.business.service.hanle;
|
||||
|
||||
public class CoilAsyncService {
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.fizz.business.service.hanle;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
@Configuration("coilTrackThreadPoolConfig")
|
||||
public class CoilTrackThreadPoolConfig {
|
||||
|
||||
@Bean("coilTrackExecutor")
|
||||
public ThreadPoolTaskExecutor coilTrackExecutor() {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
executor.setCorePoolSize(10); // 核心线程数
|
||||
executor.setMaxPoolSize(50); // 最大线程数
|
||||
executor.setQueueCapacity(2000); // 队列容量
|
||||
executor.setKeepAliveSeconds(60); // 空闲线程存活时间
|
||||
executor.setThreadNamePrefix("CoilTrackPool-");
|
||||
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 队列满策略
|
||||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,29 +4,40 @@ import com.fizz.business.anno.OpcMessageHandlerType;
|
||||
import com.fizz.business.constants.enums.OpcMessageType;
|
||||
import com.fizz.business.domain.msg.OpcMessage;
|
||||
import com.fizz.business.service.OpcMessageHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class OpcMessageDispatcher {
|
||||
|
||||
private final Map<OpcMessageType, OpcMessageHandler<? extends OpcMessage>> handlerMap = new HashMap<>();
|
||||
|
||||
@Autowired
|
||||
public OpcMessageDispatcher(ApplicationContext context) {
|
||||
Map<String, OpcMessageHandler> beans = context.getBeansOfType(OpcMessageHandler.class);
|
||||
beans.values().forEach(handler -> {
|
||||
OpcMessageHandlerType annotation = handler.getClass().getAnnotation(OpcMessageHandlerType.class);
|
||||
if (annotation != null) {
|
||||
handlerMap.put(annotation.value(), handler);
|
||||
} else {
|
||||
throw new IllegalStateException("Handler " + handler.getClass().getSimpleName() + " 未标注 @OpcMessageHandlerType");
|
||||
|
||||
Collection<OpcMessageHandler> handlers = context.getBeansOfType(OpcMessageHandler.class).values();
|
||||
|
||||
for (OpcMessageHandler handler : handlers) {
|
||||
|
||||
// ⭐⭐ 从代理类中获取注解的正确方式
|
||||
OpcMessageHandlerType annotation =
|
||||
AnnotationUtils.findAnnotation(handler.getClass(), OpcMessageHandlerType.class);
|
||||
|
||||
if (annotation == null) {
|
||||
throw new IllegalStateException(
|
||||
handler.getClass().getSimpleName() + " 未标注 @OpcMessageHandlerType");
|
||||
}
|
||||
});
|
||||
|
||||
handlerMap.put(annotation.value(), handler);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -35,7 +46,7 @@ public class OpcMessageDispatcher {
|
||||
if (handler != null) {
|
||||
handler.handle(message);
|
||||
} else {
|
||||
System.out.println("未注册的 OPC 消息类型: " + type);
|
||||
log.warn("未注册的 OPC 消息类型: {}", type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fizz.business.dto.SegmentDTO;
|
||||
import com.fizz.business.mapper.SegmentMapper;
|
||||
import com.fizz.business.vo.SegmentParamVO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
@@ -15,6 +16,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class SegmentService {
|
||||
|
||||
@Resource
|
||||
@@ -29,7 +31,7 @@ public class SegmentService {
|
||||
*/
|
||||
public void saveTotalSegment(SegmentDTO segment) {
|
||||
if (segment == null || segment.getEnCoilID() == null || segment.getEnCoilID().isEmpty()) {
|
||||
System.err.println("警告: Coil ID 为空,无法保存数据。");
|
||||
log.warn("警告: Coil ID 为空,无法保存数据。");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -45,7 +47,7 @@ public class SegmentService {
|
||||
String jsonString = objectMapper.writeValueAsString(totalValuesAvg);
|
||||
segment.setTotalValuesJson(jsonString);
|
||||
} catch (JsonProcessingException e) {
|
||||
System.err.println("转换 JSON 失败: " + e.getMessage());
|
||||
log.warn("转换 JSON 失败: " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -58,7 +60,7 @@ public class SegmentService {
|
||||
// 3. 执行插入操作,MyBatis-Plus 会自动处理 totalValuesJson 字段的保存
|
||||
segmentMapper.insert(segment);
|
||||
|
||||
System.out.println("段数据保存成功。钢卷号: " + segment.getEnCoilID() + ", 段号: " + segment.getSegNo());
|
||||
log.info("段数据保存成功。钢卷号: " + segment.getEnCoilID() + ", 段号: " + segment.getSegNo());
|
||||
}
|
||||
|
||||
public List<SegmentParamVO> queryParamByEnCoilId(String enCoilID, String paramField) {
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.fizz.business.service.strip;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class LogRateLimiter {
|
||||
private static final Map<String, Long> cache = new ConcurrentHashMap<>();
|
||||
|
||||
public static boolean shouldLog(String key, long intervalMillis) {
|
||||
long now = System.currentTimeMillis();
|
||||
Long last = cache.get(key);
|
||||
if (last == null || now - last > intervalMillis) {
|
||||
cache.put(key, now);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.fizz.business.service.strip;
|
||||
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.fizz.business.constants.enums.DeviceEnum;
|
||||
import com.fizz.business.constants.enums.L1OperateMatEnum;
|
||||
import com.fizz.business.domain.msg.AppMeasureCoatMessage;
|
||||
@@ -10,11 +11,12 @@ import com.fizz.business.dto.MatmapDTO;
|
||||
import com.fizz.business.dto.SegValue;
|
||||
import com.fizz.business.dto.SegmentDTO;
|
||||
import com.fizz.business.form.L1OperateMatForm;
|
||||
import com.fizz.business.service.LogDataService;
|
||||
import com.fizz.business.service.ProMatmapService;
|
||||
import com.fizz.business.service.TrackService;
|
||||
import com.fizz.business.service.impl.SegmentService;
|
||||
import com.fizz.business.utils.MatmapUtil;
|
||||
import com.fizz.business.utils.WebSocketUtil;
|
||||
import com.fizz.business.vo.SegmentParamVO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
@@ -27,8 +29,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import static com.fizz.business.constants.enums.DeviceEnum.WELDER;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@@ -37,7 +37,10 @@ public class SegmentTrackerService {
|
||||
private final StripPositionService stripPositionService;
|
||||
private final TrackService trackService;
|
||||
private final SegmentService segmentService; // 注入新创建的段服务
|
||||
private final LogDataService logDataService; // 注入新创建的段服务
|
||||
private final ProMatmapService proMatmapService; // 注入新创建的段服务
|
||||
|
||||
private static final long intervalTime = 10000; // 每 10 秒写一次
|
||||
private int traceCount = 0;
|
||||
private boolean firstMeasure = true;
|
||||
private BigDecimal weldLength = BigDecimal.ZERO;
|
||||
@@ -49,6 +52,15 @@ public class SegmentTrackerService {
|
||||
private final ConcurrentMap<String, Set<DeviceEnum>> coilReachedDevices = new ConcurrentHashMap<>();
|
||||
private static final double LOWSPEEDLIMIT = 0.05;
|
||||
|
||||
// 定义一个缓存记录上次写入日志的时间
|
||||
private final Map<String, Long> lastLogTimeMap = new ConcurrentHashMap<>();
|
||||
|
||||
// --- 定义一个缓存,用于控制同一 CoilId 新卷日志写入频率 ---
|
||||
private final Map<String, Long> lastNewCoilLogTimeMap = new ConcurrentHashMap<>();
|
||||
|
||||
// 放在类的字段中,全局共享
|
||||
private final Map<String, Long> lastTrackLogTimeMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 【主入口】
|
||||
* 负责处理新的测量数据,生成新段,并对新到达的设备做一次性快照。
|
||||
@@ -60,52 +72,65 @@ public class SegmentTrackerService {
|
||||
AppMeasureCoatMessage coat,
|
||||
AppMeasureExitMessage exit) {
|
||||
|
||||
// 1. 首次测量初始化或新卷判定
|
||||
long now = System.currentTimeMillis();
|
||||
Long lastTime = lastLogTimeMap.get(coilId);
|
||||
if (lastTime == null || now - lastTime > intervalTime) {
|
||||
lastLogTimeMap.put(coilId, now);
|
||||
log.info("【TRACK-START】接收到测量数据 -> CoilId: {}, LengthAtWelder: {}", coilId, entryLengthAtWelder);
|
||||
logDataService.logInfo("WELDER", "接收到测量数据 -> CoilId: " + coilId + ", LengthAtWelder: " + entryLengthAtWelder);
|
||||
}
|
||||
|
||||
// 1. 新卷或首次测量初始化
|
||||
BigDecimal weldDev;
|
||||
if (firstMeasure || entryLengthAtWelder.compareTo(weldLength) < 0) {
|
||||
weldDev = entryLengthAtWelder; // 新卷偏移量等于当前长度
|
||||
weldDev = entryLengthAtWelder;
|
||||
coilSegNum = 1;
|
||||
weldLength = entryLengthAtWelder;
|
||||
firstMeasure = false;
|
||||
listSegment.clear(); // 清空旧段
|
||||
coilReachedDevices.remove(coilId); // 清空旧钢卷的快照记录
|
||||
log.info("New coil detected or initialized:{} " ,coilId);
|
||||
listSegment.clear();
|
||||
coilReachedDevices.remove(coilId);
|
||||
|
||||
long now1 = System.currentTimeMillis();
|
||||
Long lastTime1 = lastNewCoilLogTimeMap.get(coilId);
|
||||
if (lastTime1 == null || now1 - lastTime1 > intervalTime) {
|
||||
lastNewCoilLogTimeMap.put(coilId, now1);
|
||||
log.info("【WELDER】检测到新钢卷或初始化 -> CoilId: {}", coilId);
|
||||
logDataService.logInfo("WELDER", "检测到新钢卷或初始化 -> CoilId: " + coilId);
|
||||
}
|
||||
} else {
|
||||
weldDev = entryLengthAtWelder.subtract(weldLength);
|
||||
}
|
||||
|
||||
// 更新焊机长度
|
||||
weldLength = entryLengthAtWelder;
|
||||
|
||||
// trace 控制
|
||||
traceCount++;
|
||||
if (traceCount > 5) {
|
||||
log.info(String.format("Trace: weldLen=%.2f, speed=%s",
|
||||
entryLengthAtWelder, procStripSpeed(entry, furnace, exit)));
|
||||
traceCount = 0;
|
||||
}
|
||||
|
||||
|
||||
// 2. 检查是否达到生成新段的条件
|
||||
// 2. 新段生成逻辑
|
||||
BigDecimal segThreshold = BigDecimal.valueOf(coilSegNum * SEGSTRIPLEN);
|
||||
if (entryLengthAtWelder.compareTo(segThreshold) >= 0) {
|
||||
|
||||
// 2.1. 创建新的 SegmentDTO 并初始化基本位置
|
||||
SegmentDTO newSeg = createNewSegment(coilId, entryLengthAtWelder);
|
||||
|
||||
// 2.3. 将新段添加到队列中
|
||||
listSegment.addLast(newSeg);
|
||||
if (listSegment.size() > MAX_SEG_COUNT) {
|
||||
listSegment.removeFirst();
|
||||
}
|
||||
if (listSegment.size() > MAX_SEG_COUNT) listSegment.removeFirst();
|
||||
log.info("【TRACK】新段生成 -> CoilId: {}, SegmentNo: {}, StartLen: {}", coilId, coilSegNum, entryLengthAtWelder);
|
||||
logDataService.logInfo("WELDER", "新段生成 -> CoilId: " + coilId + ", SegmentNo: " + coilSegNum + ", StartLen: " + entryLengthAtWelder);
|
||||
coilSegNum++;
|
||||
}
|
||||
|
||||
// 3. 处理队列中所有已存在的段
|
||||
treatSegAsync(entry, furnace, coat, exit, weldDev);
|
||||
// 3. 更新已有段
|
||||
treatSeg(entry, furnace, coat, exit, weldDev);
|
||||
|
||||
// 4. trackCoilHeadPosition 同步执行
|
||||
try {
|
||||
log.warn(">>> trackCoilHeadPosition start, thread: {}, coilId: {}", Thread.currentThread().getName(), coilId);
|
||||
trackCoilHeadPosition(coilId, entryLengthAtWelder, entry, exit);
|
||||
} catch (Exception e) {
|
||||
log.error("trackCoilHeadPosition 执行异常,coilId=" + coilId, e);
|
||||
}
|
||||
|
||||
// 5. 完成日志
|
||||
log.info("【TRACK-END】CoilId: {}, 当前长度: {}, 已生成段数: {}", coilId, entryLengthAtWelder, coilSegNum);
|
||||
logDataService.logInfo("TRACK", "处理完成 -> CoilId: " + coilId + ", 当前长度: " + entryLengthAtWelder + ", 已生成段数: " + coilSegNum);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 【核心功能】
|
||||
* 遍历所有已存在的段,更新其位置,并累积其在设备区域内的实时数据。
|
||||
@@ -117,12 +142,19 @@ public class SegmentTrackerService {
|
||||
AppMeasureExitMessage exit,
|
||||
BigDecimal weldDev) {
|
||||
if (listSegment.isEmpty()) {
|
||||
// === 【处理开始日志】===
|
||||
log.warn("【TRACK-TREAT】,listSegment为空,直接返回");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
BigDecimal celLength = entry != null ? entry.getCelLength() : BigDecimal.ZERO;
|
||||
BigDecimal cxlLength = exit != null ? exit.getCxlLength() : BigDecimal.ZERO;
|
||||
|
||||
// === 【处理开始日志】===
|
||||
log.info("【TRACK-TREAT】开始处理段数据,共 {} 段,weldDev={},celLength = {},cxlLength = {}。 ", listSegment.size(), weldDev, celLength, cxlLength);
|
||||
logDataService.logInfo("TRACK", "开始处理段数据,共 " + listSegment.size() + " 段,weldDev=" + weldDev);
|
||||
|
||||
Iterator<SegmentDTO> iterator = listSegment.descendingIterator();
|
||||
while (iterator.hasNext()) {
|
||||
SegmentDTO segment = iterator.next();
|
||||
@@ -139,8 +171,14 @@ public class SegmentTrackerService {
|
||||
if (segment.getHeadPos().compareTo(BigDecimal.valueOf(currentDevicePos)) > 0 &&
|
||||
segment.getTailPos().compareTo(BigDecimal.valueOf(currentDevicePos)) < 0) {
|
||||
|
||||
log.info("【TRACK-TREAT】段 {} 进入设备区域 [{}],当前设备长度:{}", segment.getSegNo(), device.name(), currentDevicePos);
|
||||
logDataService.logInfo("TRACK",
|
||||
"段 " + segment.getSegNo() + " 进入设备区域 [" + device.name() + "],当前设备长度:" + currentDevicePos);
|
||||
double currentSpeed = getSpeedForDevice(device, entry, coat, exit);
|
||||
if (currentSpeed > LOWSPEEDLIMIT) {
|
||||
log.info("【TRACK-TREAT】段 {} 速度大于基准速度, 进入设备区域 [{}],当前速度:{}", segment.getSegNo(), device.name(), currentSpeed);
|
||||
logDataService.logInfo("TRACK",
|
||||
"段 " + segment.getSegNo() + " 进入设备区域 [" + device.name() + "],当前速度:" + currentSpeed);
|
||||
for (String fieldName : device.getParamFields()) {
|
||||
Object message = getMessageForDevice(device, entry, furnace, coat, exit);
|
||||
if (message != null) {
|
||||
@@ -155,7 +193,10 @@ public class SegmentTrackerService {
|
||||
|
||||
double exitPlantPos = stripPositionService.calculate(DeviceEnum.TR, celLength, cxlLength);
|
||||
if (segment.getTailPos().compareTo(BigDecimal.valueOf(exitPlantPos)) >= 0) {
|
||||
System.out.println("钢卷 " + segment.getEnCoilID() + " 的段号 " + segment.getSegNo() + " 已离开产线,开始持久化数据。");
|
||||
log.info("【TRACK-END】钢卷 {} 的段号 {} 已离开产线,开始持久化数据{}。",
|
||||
segment.getEnCoilID(), segment.getSegNo(), JSONUtil.toJsonStr(segment.getTotalValues()));
|
||||
logDataService.logInfo("SEGMENT",
|
||||
"钢卷 " + segment.getEnCoilID() + " 的段号 " + segment.getSegNo() + " 已离开产线,开始持久化数据。");
|
||||
segmentService.saveTotalSegment(segment); // 调用服务进行持久化
|
||||
iterator.remove();
|
||||
}
|
||||
@@ -163,22 +204,22 @@ public class SegmentTrackerService {
|
||||
}
|
||||
|
||||
// --- 新增的辅助方法,将逻辑封装起来 ---
|
||||
|
||||
/**
|
||||
* 【异步方法】
|
||||
* 异步处理队列中所有已存在的段,更新其位置和累积数据。
|
||||
*/
|
||||
@Async("taskExecutor") // 指定使用名为 "taskExecutor" 的线程池
|
||||
public void treatSegAsync(AppMeasureEntryMessage entry,
|
||||
AppMeasureFurnaceMessage furnace,
|
||||
AppMeasureCoatMessage coat,
|
||||
AppMeasureExitMessage exit,
|
||||
BigDecimal weldDev) {
|
||||
AppMeasureFurnaceMessage furnace,
|
||||
AppMeasureCoatMessage coat,
|
||||
AppMeasureExitMessage exit,
|
||||
BigDecimal weldDev) {
|
||||
// 调用原有的同步方法
|
||||
this.treatSeg(entry, furnace, coat, exit, weldDev);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 创建并初始化一个新的 SegmentDTO。
|
||||
*/
|
||||
@@ -208,30 +249,54 @@ public class SegmentTrackerService {
|
||||
}
|
||||
|
||||
|
||||
// --- 辅助方法,与消息处理和反射相关 ---
|
||||
|
||||
private Object getMessageForDevice(DeviceEnum device, AppMeasureEntryMessage entry, AppMeasureFurnaceMessage furnace, AppMeasureCoatMessage coat, AppMeasureExitMessage exit) {
|
||||
if (device.getDesc().contains("开卷机") || device.getDesc().contains("活套") || device.getDesc().contains("焊机")) {
|
||||
return entry;
|
||||
} else if (device.getDesc().contains("清洗段") || device.getDesc().contains("退火炉")) {
|
||||
return furnace;
|
||||
} else if (device.getDesc().contains("涂机")) {
|
||||
return coat;
|
||||
} else {
|
||||
return exit;
|
||||
private Object getMessageForDevice(DeviceEnum device,
|
||||
AppMeasureEntryMessage entry,
|
||||
AppMeasureFurnaceMessage furnace,
|
||||
AppMeasureCoatMessage coat,
|
||||
AppMeasureExitMessage exit) {
|
||||
switch (device.getSourceType()) {
|
||||
case ENTRY:
|
||||
return entry;
|
||||
case FURNACE:
|
||||
return furnace;
|
||||
case COAT:
|
||||
return coat;
|
||||
case EXIT:
|
||||
return exit;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private double getSpeedForDevice(DeviceEnum device, AppMeasureEntryMessage entry, AppMeasureCoatMessage coat, AppMeasureExitMessage exit) {
|
||||
if (device.getDesc().contains("开卷机") || device.getDesc().contains("活套") || device.getDesc().contains("焊机")) {
|
||||
return entry != null && entry.getStripSpeed() != null ? entry.getStripSpeed().doubleValue() : 0.0;
|
||||
} else if (device.getDesc().contains("清洗段") || device.getDesc().contains("退火炉")) {
|
||||
return coat != null && coat.getStripSpeedTmExit() != null ? coat.getStripSpeedTmExit().doubleValue() : 0.0;
|
||||
} else {
|
||||
return exit != null && exit.getSpeedExitSection() != null ? exit.getSpeedExitSection().doubleValue() : 0.0;
|
||||
|
||||
private double getSpeedForDevice(DeviceEnum device,
|
||||
AppMeasureEntryMessage entry,
|
||||
AppMeasureCoatMessage coat,
|
||||
AppMeasureExitMessage exit) {
|
||||
switch (device.getSectionType()) {
|
||||
case ENTRY:
|
||||
// 入口段设备:速度来自 entry
|
||||
return entry != null && entry.getStripSpeed() != null
|
||||
? entry.getStripSpeed().doubleValue()
|
||||
: 0.0;
|
||||
|
||||
case PROCESS:
|
||||
|
||||
return coat != null && coat.getStripSpeedTmExit() != null
|
||||
? coat.getStripSpeedTmExit().doubleValue()
|
||||
: 0.0;
|
||||
|
||||
case EXIT:
|
||||
// 出口段设备:速度来自 exit
|
||||
return exit != null && exit.getSpeedExitSection() != null
|
||||
? exit.getSpeedExitSection().doubleValue()
|
||||
: 0.0;
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private double procStripSpeed(AppMeasureEntryMessage entry, AppMeasureFurnaceMessage furnace, AppMeasureExitMessage exit) {
|
||||
if (entry != null && entry.getStripSpeed() != null) return entry.getStripSpeed().doubleValue();
|
||||
// if (furnace != null && furnace.getStripSpeed() != null) return furnace.getStripSpeed().doubleValue();
|
||||
@@ -265,48 +330,55 @@ public class SegmentTrackerService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 【新方法】
|
||||
* 专门用于处理钢卷头部在设备间的移动和物料跟踪。
|
||||
* 这部分逻辑包含了对 Redis/DB 的写入,最适合异步化。
|
||||
*/
|
||||
@Async("taskExecutor")
|
||||
// 本地缓存,每个 coilId 对应已到达设备
|
||||
public void trackCoilHeadPosition(String coilId, BigDecimal headPos,
|
||||
AppMeasureEntryMessage entry, AppMeasureExitMessage exit) {
|
||||
|
||||
Set<DeviceEnum> prevReached = coilReachedDevices.computeIfAbsent(coilId, k -> Collections.newSetFromMap(new ConcurrentHashMap<>()));
|
||||
log.warn(">>> trackCoilHeadPosition 当前线程:{}", Thread.currentThread().getName());
|
||||
|
||||
if (LogRateLimiter.shouldLog("TRACK:" + coilId, 5000)) {
|
||||
log.info("焊缝位置匹配逻辑,当前焊缝长度{},", headPos);
|
||||
logDataService.logInfo("MATMAP-TRACK", "CoilId=" + coilId + " ...");
|
||||
}
|
||||
|
||||
Set<DeviceEnum> prevReached = coilReachedDevices.computeIfAbsent(coilId,
|
||||
k -> Collections.newSetFromMap(new ConcurrentHashMap<>()));
|
||||
|
||||
if (LogRateLimiter.shouldLog("TRACK:" + coilId, 5000)) {
|
||||
logDataService.logInfo("MATMAP-TRACK", "构建的本地matmap缓存为=" + JSONUtil.toJsonStr(prevReached) + " ...");
|
||||
}
|
||||
|
||||
BigDecimal celLength = entry != null ? entry.getCelLength() : BigDecimal.ZERO;
|
||||
BigDecimal cxlLength = exit != null ? exit.getCxlLength() : BigDecimal.ZERO;
|
||||
|
||||
for (DeviceEnum d : DeviceEnum.values()) {
|
||||
double dynPos = stripPositionService.calculate(d, celLength, cxlLength);
|
||||
log.info("焊缝位置匹配逻辑,当前焊缝长度{},当前计算的设备长度:{}", headPos, dynPos);
|
||||
|
||||
// 判断钢卷的头部是否首次到达该设备
|
||||
if (headPos.compareTo(BigDecimal.valueOf(dynPos)) >= 0) {
|
||||
if (!prevReached.contains(d)) {
|
||||
if (headPos.compareTo(BigDecimal.valueOf(dynPos)) >= 0 && !prevReached.contains(d)) {
|
||||
|
||||
// 1. 如果是焊机,则调用 CRM 更新计划状态
|
||||
if (d == WELDER) {
|
||||
|
||||
MatmapDTO matmap = MatmapUtil.getMatmap(WELDER.getIdx());
|
||||
trackService.l1OperateMat(L1OperateMatForm.builder()
|
||||
.entryMatId(coilId)
|
||||
.planId(matmap.getPlanId())
|
||||
.porIdx(entry.getPayOffReelNumber())
|
||||
.operation(L1OperateMatEnum.PRODUCING)
|
||||
.build());
|
||||
}
|
||||
|
||||
// 2. 更新 Matmap
|
||||
if (d == DeviceEnum.WELDER) {
|
||||
logDataService.logInfo("MATMAP-TRACK", "钢卷到达焊机,更新钢卷计划状态coil=" + coilId + "当前长度为:" + headPos);
|
||||
MatmapDTO matmap = MatmapUtil.getMatmap(DeviceEnum.WELDER.getIdx());
|
||||
trackService.l1OperateMat(L1OperateMatForm.builder()
|
||||
.entryMatId(coilId)
|
||||
.planId(matmap.getPlanId())
|
||||
.porIdx(entry.getPayOffReelNumber())
|
||||
.operation(L1OperateMatEnum.PRODUCING)
|
||||
.build());
|
||||
} else {
|
||||
logDataService.logInfo("MATMAP-TRACK", "钢卷:" + coilId + "到达设备:" + d.getDesc() + "当前长度为:" + headPos);
|
||||
MatmapUtil.setMatId(d.getIdx(), coilId);
|
||||
proMatmapService.flushMatmap();
|
||||
WebSocketUtil.sendMatmapMsg();
|
||||
// 3. 标记为已到达,防止重复操作
|
||||
prevReached.add(d);
|
||||
}
|
||||
|
||||
prevReached.add(d); // 标记为已到达
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,68 +1,70 @@
|
||||
package com.fizz.business.service.strip;
|
||||
|
||||
import com.fizz.business.constants.enums.DeviceEnum;
|
||||
import com.fizz.business.domain.msg.AppMeasureEntryMessage;
|
||||
import com.fizz.business.domain.msg.AppMeasureExitMessage;
|
||||
import com.fizz.business.service.LogDataService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 位置计算服务 —— 根据 entry.stripLocation(焊机参考)和活套长度动态判断设备的比较位置
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class StripPositionService {
|
||||
|
||||
/**
|
||||
* 计算设备在 entry 坐标系的“比较位置”
|
||||
*
|
||||
* 规则:
|
||||
* - device.basePosition < ENL_MIN : 不加活套
|
||||
* - ENL_MIN <= device.basePosition < CXL_MIN : 加 celLength
|
||||
* - >= CXL_MIN : 加 cxlLength
|
||||
*/
|
||||
@Resource
|
||||
LogDataService logDataService;
|
||||
|
||||
public double calculate(DeviceEnum device, BigDecimal celLength, BigDecimal cxlLength) {
|
||||
double base = device.getBasePosition();
|
||||
double cel = celLength == null ? 0.0 : celLength.doubleValue();
|
||||
double cxl = cxlLength == null ? 0.0 : cxlLength.doubleValue();
|
||||
|
||||
double enlMin = findEnlMin();
|
||||
double cxlMin = findCxlMin();
|
||||
double result;
|
||||
|
||||
if (base < enlMin) {
|
||||
return base;
|
||||
} else if (base < cxlMin) {
|
||||
return base + cel;
|
||||
} else {
|
||||
return base + cxl;
|
||||
switch (device.getSectionType()) {
|
||||
case ENTRY:
|
||||
// 入口段:不开活套
|
||||
result = base;
|
||||
break;
|
||||
|
||||
case PROCESS:
|
||||
// 工艺段:加入口活套偏移
|
||||
result = base + cel;
|
||||
break;
|
||||
|
||||
case EXIT:
|
||||
// 出口段:加入口 + 出口活套偏移
|
||||
result = base + cel + cxl;
|
||||
break;
|
||||
|
||||
default:
|
||||
result = base;
|
||||
}
|
||||
}
|
||||
|
||||
public double calculate(DeviceEnum device,AppMeasureEntryMessage entry,
|
||||
AppMeasureExitMessage exit) {
|
||||
BigDecimal cel = entry == null ? null : entry.getCelLength();
|
||||
BigDecimal cxl = exit == null ? null : exit.getCxlLength();
|
||||
return calculate(device, cel, cxl);
|
||||
}
|
||||
|
||||
private double findEnlMin() {
|
||||
double min = Double.MAX_VALUE;
|
||||
for (DeviceEnum d : DeviceEnum.values()) {
|
||||
if (d.name().startsWith("ENL")) {
|
||||
min = Math.min(min, d.getBasePosition());
|
||||
}
|
||||
// === 日志输出(控制频率,防止刷屏)===
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("【POSITION-CALC】设备: {}, 区域: {}, Base: {}, Cel: {}, Cxl: {}, 结果: {}",
|
||||
device.getDesc(),
|
||||
device.getSectionType(),
|
||||
String.format("%.3f", base),
|
||||
String.format("%.3f", cel),
|
||||
String.format("%.3f", cxl),
|
||||
String.format("%.3f", result)
|
||||
);
|
||||
}
|
||||
return min == Double.MAX_VALUE ? 0.0 : min;
|
||||
|
||||
// 可选:持久化关键信息(只针对关键设备或每隔一段时间)
|
||||
if (device == DeviceEnum.WELDER || device == DeviceEnum.COAT || device == DeviceEnum.TR) {
|
||||
logDataService.logInfo("POSITION",
|
||||
String.format("设备:%s | 区域:%s | Base:%.3f | Cel:%.3f | Cxl:%.3f | Result:%.3f",
|
||||
device.getDesc(), device.getSectionType(), base, cel, cxl, result));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private double findCxlMin() {
|
||||
double min = Double.MAX_VALUE;
|
||||
for (DeviceEnum d : DeviceEnum.values()) {
|
||||
if (d.name().startsWith("CXL")) {
|
||||
min = Math.min(min, d.getBasePosition());
|
||||
}
|
||||
}
|
||||
return min == Double.MAX_VALUE ? Double.MAX_VALUE : min;
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.fizz.business.domain.ProMatmap;
|
||||
import com.fizz.business.dto.MatmapDTO;
|
||||
import com.fizz.business.mapper.ProMatmapMapper;
|
||||
import com.fizz.business.service.LogDataService;
|
||||
import com.fizz.business.service.client.RedisCacheManager;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -29,8 +30,14 @@ import java.util.stream.Collectors;
|
||||
public class MatmapUtil {
|
||||
|
||||
private static ProMatmapMapper romtbMatmapMapper;
|
||||
private static LogDataService logDataService;
|
||||
private static RedisCacheManager redisCacheManager;
|
||||
|
||||
@Autowired
|
||||
public void setLogDataService(LogDataService logDataService) {
|
||||
MatmapUtil.logDataService = logDataService;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setRomtbMatmapMapper(ProMatmapMapper romtbMatmapMapper) {
|
||||
MatmapUtil.romtbMatmapMapper = romtbMatmapMapper;
|
||||
@@ -69,6 +76,9 @@ public class MatmapUtil {
|
||||
}
|
||||
matmap.setPosIdx(index);
|
||||
matmap.setMatId(matId);
|
||||
log.info("钢卷焊缝跟踪:matId{},位置id:{}",matId,index);
|
||||
logDataService.logInfo("MATMAP-SAVE","钢卷焊缝跟踪:matId"+matId+",位置id:"+index);
|
||||
|
||||
redisCacheManager.setMatmap(index, matmap);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
|
||||
/**
|
||||
@@ -13,6 +14,7 @@ import org.springframework.scheduling.annotation.EnableAsync;
|
||||
*/
|
||||
@ComponentScan(basePackages = {"com.ruoyi","com.fizz"})
|
||||
@EnableAsync // 启用异步处理
|
||||
@EnableAspectJAutoProxy(exposeProxy = true)
|
||||
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
|
||||
public class RuoYiApplication
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user