From df8b6874eef7acef4a8687026ab3818b70823ded Mon Sep 17 00:00:00 2001 From: zhouhao Date: Thu, 5 Mar 2026 16:32:10 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E8=AE=BE=E5=A4=87=E6=8C=87=E6=A0=87):=20?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=89=B9=E9=87=8F=E8=8E=B7=E5=8F=96=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E5=B1=9E=E6=80=A7=E6=8C=87=E6=A0=87=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../metric/DefaultPropertyMetricManager.java | 133 ++++++++++++++++-- .../device/web/DeviceInstanceController.java | 10 ++ 2 files changed, 128 insertions(+), 15 deletions(-) diff --git a/jetlinks-components/things-component/src/main/java/org/jetlinks/community/things/impl/metric/DefaultPropertyMetricManager.java b/jetlinks-components/things-component/src/main/java/org/jetlinks/community/things/impl/metric/DefaultPropertyMetricManager.java index d48a53fe..4348a59e 100644 --- a/jetlinks-components/things-component/src/main/java/org/jetlinks/community/things/impl/metric/DefaultPropertyMetricManager.java +++ b/jetlinks-components/things-component/src/main/java/org/jetlinks/community/things/impl/metric/DefaultPropertyMetricManager.java @@ -15,6 +15,8 @@ */ package org.jetlinks.community.things.impl.metric; +import lombok.Getter; +import org.apache.commons.collections4.CollectionUtils; import org.hswebframework.ezorm.rdb.mapping.ReactiveRepository; import org.hswebframework.ezorm.rdb.mapping.defaults.SaveResult; import org.hswebframework.web.crud.events.EntityCreatedEvent; @@ -33,13 +35,16 @@ import org.jetlinks.community.gateway.annotation.Subscribe; import org.jetlinks.community.things.impl.entity.PropertyMetricEntity; import org.jetlinks.community.things.metric.AbstractPropertyMetricManager; import org.springframework.context.event.EventListener; +import org.springframework.transaction.annotation.Transactional; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.util.Collections; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.function.Function; +import java.util.stream.Collectors; public class DefaultPropertyMetricManager extends AbstractPropertyMetricManager { @@ -79,22 +84,105 @@ public class DefaultPropertyMetricManager extends AbstractPropertyMetricManager .map(PropertyMetadataConstants.Metrics::getMetrics) .orElse(Collections.emptyList())) .collectMap(PropertyMetric::getId, Function.identity(), LinkedHashMap::new), - (exists, inMetadata) -> { - for (Map.Entry entry : exists.entrySet()) { - String metric = entry.getKey(); - PropertyMetric independent = entry.getValue(); - PropertyMetric fromMetadata = inMetadata.get(metric); - if (fromMetadata == null) { - inMetadata.put(metric, independent); - continue; - } - fromMetadata.setValue(independent.getValue()); - } - return Flux.fromIterable(inMetadata.values()); - }) + this::merge) .flatMapMany(Function.identity()); } + /** + * 批量获取指标 + * + * @param thingType 物类型 + * @param thingId 物ID + * @param properties 属性列表 + * @return 指标信息 + */ + public Flux getPropertyMetrics(String thingType, + String thingId, + List properties) { + if (CollectionUtils.isEmpty(properties)) { + return Flux.empty(); + } + + //数据库中记录的 + Mono>> existsByProperty = repository + .createQuery() + .where(PropertyMetricEntity::getThingType, thingType) + .and(PropertyMetricEntity::getThingId, thingId) + .in(PropertyMetricEntity::getProperty, properties) + .fetch() + .groupBy(PropertyMetricEntity::getProperty) + .flatMap(group -> group + .map(PropertyMetricEntity::toMetric) + .collectMap(PropertyMetric::getId, Function.identity()) + .map(map -> Map.entry(group.key(), map))) + .collectMap(Map.Entry::getKey, Map.Entry::getValue); + + //物模型中配置的 + Mono>> metadataByProperty = registry + .getThing(thingType, thingId) + .flatMap(Thing::getTemplate) + .flatMap(ThingTemplate::getMetadata) + .flatMapMany(metadata -> Flux + .fromIterable(properties) + .map(prop -> Map.entry( + prop, + metadata + .getProperty(prop) + .map(PropertyMetadataConstants.Metrics::getMetrics) + .orElse(Collections.emptyList()) + ))) + .flatMap(entry -> Flux + .fromIterable(entry.getValue()) + .collectMap(PropertyMetric::getId, Function.identity()) + .map(map -> Map.entry(entry.getKey(), map))) + .collectMap(Map.Entry::getKey, Map.Entry::getValue, LinkedHashMap::new); + + return Mono + .zip(existsByProperty, metadataByProperty) + .flatMapMany(tuple -> { + Map> exists = tuple.getT1(); + Map> metadata = tuple.getT2(); + + return Flux + .fromIterable(properties) + .flatMap(prop -> { + Map existsMetrics = exists.getOrDefault(prop, Collections.emptyMap()); + Map metadataMetrics = new LinkedHashMap<>(metadata.getOrDefault(prop, Collections.emptyMap())); + + return merge(existsMetrics, metadataMetrics) + .collectList() + .map(metrics -> new DevicePropertyMetricInfo(prop, metrics)); + }); + }); + } + + @Getter + public static class DevicePropertyMetricInfo { + private final String property; + private final List metrics; + + public DevicePropertyMetricInfo(String property, List metrics) { + this.property = property; + this.metrics = metrics; + } + } + + private Flux merge(Map exists, + Map inMetadata) { + for (Map.Entry entry : exists.entrySet()) { + String metric = entry.getKey(); + PropertyMetric independent = entry.getValue(); + PropertyMetric fromMetadata = inMetadata.get(metric); + if (fromMetadata == null) { + inMetadata.put(metric, independent); + continue; + } + fromMetadata.setValue(independent.getValue()); + } + return Flux.fromIterable(inMetadata.values()); + } + + @Transactional public Mono savePropertyMetrics(String thingType, String thingId, String property, @@ -112,7 +200,22 @@ public class DefaultPropertyMetricManager extends AbstractPropertyMetricManager entity.genericId(); return entity; }) - .as(repository::save); + .collectList() + .flatMap(list -> { + List ids = list.stream().map(PropertyMetricEntity::getId).collect(Collectors.toList()); + return repository + .createDelete() + .where(PropertyMetricEntity::getThingType, thingType) + .and(PropertyMetricEntity::getThingId, thingId) + .and(PropertyMetricEntity::getProperty, property) + // 删除当前物模型中的其他指标 + .when(CollectionUtils.isNotEmpty(ids), + delete -> delete.notIn(PropertyMetricEntity::getId, ids)) + .execute() + .then( + repository.save(list) + ); + }); } @@ -171,4 +274,4 @@ public class DefaultPropertyMetricManager extends AbstractPropertyMetricManager .publish("/_sys/thing-property-metric/clear-cache", key) .then(); } -} +} \ No newline at end of file diff --git a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/DeviceInstanceController.java b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/DeviceInstanceController.java index 59175d99..9f22a7d8 100644 --- a/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/DeviceInstanceController.java +++ b/jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/DeviceInstanceController.java @@ -1149,6 +1149,16 @@ public class DeviceInstanceController implements .getPropertyMetrics(DeviceThingType.device.getId(), deviceId, property); } + @PostMapping("/{deviceId}/metric/properties") + @Operation(summary = "批量获取设备属性指标数据") + @QueryAction + public Flux getPropertyMetrics(@PathVariable String deviceId, + @RequestBody Mono> payload) { + return payload + .flatMapMany(properties -> metricManager + .getPropertyMetrics(DeviceThingType.device.getId(), deviceId, properties)); + } + //仅解析文件为属性物模型 @PostMapping(value = "/{productId}/property-metadata/file/analyze") @SaveAction