|
@@ -1,23 +1,29 @@
|
|
|
package cn.vber.collection.core;
|
|
package cn.vber.collection.core;
|
|
|
|
|
|
|
|
import cn.vber.collection.domain.CollectRuleEntity;
|
|
import cn.vber.collection.domain.CollectRuleEntity;
|
|
|
|
|
+import cn.vber.collection.domain.CollectedDataPoint;
|
|
|
import cn.vber.collection.domain.CollectorEntity;
|
|
import cn.vber.collection.domain.CollectorEntity;
|
|
|
import cn.vber.collection.handler.DataPointHandler;
|
|
import cn.vber.collection.handler.DataPointHandler;
|
|
|
import cn.vber.collection.utils.ModbusTcpHelper;
|
|
import cn.vber.collection.utils.ModbusTcpHelper;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
import java.math.BigDecimal;
|
|
|
|
|
+import java.time.LocalDateTime;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
import java.util.concurrent.*;
|
|
import java.util.concurrent.*;
|
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
+import static cn.hutool.core.convert.Convert.toDouble;
|
|
|
|
|
+
|
|
|
@Slf4j
|
|
@Slf4j
|
|
|
public class DatabaseDrivenModbusCollector {
|
|
public class DatabaseDrivenModbusCollector {
|
|
|
|
|
|
|
|
private final Map<Long, RuleLoader.CollectorWithRules> collectorGroups;
|
|
private final Map<Long, RuleLoader.CollectorWithRules> collectorGroups;
|
|
|
private final ScheduledExecutorService scheduler;
|
|
private final ScheduledExecutorService scheduler;
|
|
|
private final ThreadPoolExecutor executor;
|
|
private final ThreadPoolExecutor executor;
|
|
|
|
|
+ // 2. 数据处理线程池(必须新增!)
|
|
|
|
|
+ private final ExecutorService dataHandlerExecutor;
|
|
|
private final DataPointHandler dataHandler;
|
|
private final DataPointHandler dataHandler;
|
|
|
|
|
|
|
|
|
|
|
|
@@ -35,6 +41,13 @@ public class DatabaseDrivenModbusCollector {
|
|
|
new ArrayBlockingQueue<>(groups.size()),
|
|
new ArrayBlockingQueue<>(groups.size()),
|
|
|
new ThreadPoolExecutor.CallerRunsPolicy()
|
|
new ThreadPoolExecutor.CallerRunsPolicy()
|
|
|
);
|
|
);
|
|
|
|
|
+ // 初始化数据处理线程池 👇
|
|
|
|
|
+ this.dataHandlerExecutor = new ThreadPoolExecutor(
|
|
|
|
|
+ 2, 4, 60L, TimeUnit.SECONDS,
|
|
|
|
|
+ new LinkedBlockingQueue<>(1000),
|
|
|
|
|
+ r -> new Thread(r, "modbus-data-handler"),
|
|
|
|
|
+ new ThreadPoolExecutor.CallerRunsPolicy()
|
|
|
|
|
+ );
|
|
|
}
|
|
}
|
|
|
public void start() {
|
|
public void start() {
|
|
|
for (var entry : collectorGroups.entrySet()) {
|
|
for (var entry : collectorGroups.entrySet()) {
|
|
@@ -49,6 +62,31 @@ public class DatabaseDrivenModbusCollector {
|
|
|
);
|
|
);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ // 在 DatabaseDrivenModbusCollector.pollCollectorGroup 中
|
|
|
|
|
+ private void processRule(CollectRuleEntity rule, Object rawValue, BigDecimal convertA, BigDecimal convertB) {
|
|
|
|
|
+ // 1. 计算转换值
|
|
|
|
|
+ double x = toDouble(rawValue);
|
|
|
|
|
+ double converted = convertA.doubleValue() * x + convertB.doubleValue();
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 创建不可变快照(此时固化时间戳!)
|
|
|
|
|
+ CollectedDataPoint dataPoint = CollectedDataPoint.builder()
|
|
|
|
|
+ .collectorId(rule.getCollectorId())
|
|
|
|
|
+ .ruleId(rule.getId())
|
|
|
|
|
+ .rawValue(converted)
|
|
|
|
|
+ .stringValue(String.valueOf(converted))
|
|
|
|
|
+ .dataUnit(rule.getDataUnit())
|
|
|
|
|
+ .insertTime(LocalDateTime.now()) // ⚠️ 关键:在此刻固化时间!
|
|
|
|
|
+ .build();
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 异步提交给处理器(避免阻塞采集线程)
|
|
|
|
|
+ CompletableFuture.runAsync(() -> {
|
|
|
|
|
+ try {
|
|
|
|
|
+ dataHandler.handle(dataPoint); // 传入的是独立副本
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("数据处理失败, ruleId={}", rule.getId(), e);
|
|
|
|
|
+ }
|
|
|
|
|
+ }, dataHandlerExecutor); // 使用独立线程池
|
|
|
|
|
+ }
|
|
|
private void pollCollectorGroup(RuleLoader.CollectorWithRules group) {
|
|
private void pollCollectorGroup(RuleLoader.CollectorWithRules group) {
|
|
|
executor.execute(() -> {
|
|
executor.execute(() -> {
|
|
|
CollectorEntity collector = group.collector();
|
|
CollectorEntity collector = group.collector();
|
|
@@ -70,7 +108,8 @@ public class DatabaseDrivenModbusCollector {
|
|
|
try {
|
|
try {
|
|
|
Object rawValue = readRawValue(helper, rule);
|
|
Object rawValue = readRawValue(helper, rule);
|
|
|
double converted = applyLinearTransform(rawValue, rule);
|
|
double converted = applyLinearTransform(rawValue, rule);
|
|
|
- dataHandler.handle(rule, rawValue, converted);
|
|
|
|
|
|
|
+ //dataHandler.handle(rule, rawValue, converted);
|
|
|
|
|
+ processRule(rule, rawValue, rule.getConvertA(), rule.getConvertB());
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
log.error("规则 [{}] 读取失败: {}", rule.getId(), e.getMessage());
|
|
log.error("规则 [{}] 读取失败: {}", rule.getId(), e.getMessage());
|
|
|
}
|
|
}
|