فهرست منبع

属性增加手动写值,当物模型配置了手动写值时,下发修改属性指令将不再发送到设备,而是直接入库并返回成功。

zhou-hao 4 سال پیش
والد
کامیت
98e89d8c9b

+ 85 - 0
jetlinks-components/common-component/src/main/java/org/jetlinks/community/PropertyMetadataConstants.java

@@ -0,0 +1,85 @@
+package org.jetlinks.community;
+
+import org.jetlinks.core.metadata.PropertyMetadata;
+import org.jetlinks.reactor.ql.utils.CastUtils;
+
+public interface PropertyMetadataConstants {
+
+    /**
+     * 属性来源
+     */
+    interface Source {
+        //数据来源
+        String id = "source";
+
+        //手动写值
+        String manual = "manual";
+
+        //规则,虚拟属性
+        String rule = "rule";
+
+        /**
+         * 判断属性是否手动赋值
+         *
+         * @param metadata 属性物模型
+         * @return 是否手动赋值
+         */
+        static boolean isManual(PropertyMetadata metadata) {
+            return metadata.getExpand(id)
+                           .map(manual::equals)
+                           .orElse(false);
+        }
+
+        /**
+         * 判断属性是否为规则
+         *
+         * @param metadata 物模型
+         * @return 是否规则
+         */
+        static boolean isRule(PropertyMetadata metadata) {
+            return  metadata
+                .getExpand(id)
+                .map(rule::equals)
+                .orElse(false);
+        }
+    }
+
+    /**
+     * 属性读写模式
+     */
+    interface AccessMode {
+        String id = "accessMode";
+
+        //读
+        String read = "r";
+        //写
+        String write = "w";
+        //上报
+        String report = "u";
+
+        static boolean isRead(PropertyMetadata property) {
+            return property
+                .getExpand(id)
+                .map(val -> val.toString().contains(read))
+                .orElse(true);
+        }
+
+        static boolean isWrite(PropertyMetadata property) {
+            return property
+                .getExpand(id)
+                .map(val -> val.toString().contains(write))
+                .orElseGet(() -> property
+                    .getExpand("readOnly")
+                    .map(readOnly -> !CastUtils.castBoolean(readOnly))
+                    .orElse(true)
+                );
+        }
+
+        static boolean isReport(PropertyMetadata property) {
+            return property
+                .getExpand(id)
+                .map(val -> val.toString().contains(report))
+                .orElse(true);
+        }
+    }
+}

+ 46 - 12
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/message/DeviceMessageSendLogInterceptor.java

@@ -3,15 +3,22 @@ package org.jetlinks.community.device.message;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.hswebframework.web.logger.ReactiveLogger;
 import org.hswebframework.web.logger.ReactiveLogger;
+import org.jetlinks.community.PropertyMetadataConstants;
 import org.jetlinks.core.device.DeviceOperator;
 import org.jetlinks.core.device.DeviceOperator;
 import org.jetlinks.core.device.DeviceRegistry;
 import org.jetlinks.core.device.DeviceRegistry;
 import org.jetlinks.core.event.EventBus;
 import org.jetlinks.core.event.EventBus;
 import org.jetlinks.core.message.ChildDeviceMessage;
 import org.jetlinks.core.message.ChildDeviceMessage;
 import org.jetlinks.core.message.DeviceMessage;
 import org.jetlinks.core.message.DeviceMessage;
+import org.jetlinks.core.message.Message;
 import org.jetlinks.core.message.interceptor.DeviceMessageSenderInterceptor;
 import org.jetlinks.core.message.interceptor.DeviceMessageSenderInterceptor;
+import org.jetlinks.core.message.property.WritePropertyMessage;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
+import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 import reactor.core.publisher.Mono;
 
 
+import java.util.Map;
+import java.util.function.Function;
+
 /**
 /**
  * 发送设备指令的时候,将消息推送到网关中.
  * 发送设备指令的时候,将消息推送到网关中.
  *
  *
@@ -27,26 +34,53 @@ public class DeviceMessageSendLogInterceptor implements DeviceMessageSenderInter
 
 
     private final DeviceRegistry registry;
     private final DeviceRegistry registry;
 
 
-    public Mono<Void> doPublish(Mono<DeviceOperator> device, DeviceMessage message) {
-        return device
-            .zipWhen(DeviceOperator::getProduct)
-            .doOnNext(tp2 -> message.addHeader("productId", tp2.getT2().getId()))
-            .flatMap(tp2 -> {
-                String topic = DeviceMessageConnector.createDeviceMessageTopic(tp2.getT2().getId(),tp2.getT1().getDeviceId(),message);
-
+    public Mono<Void> doPublish(Message message) {
+        return DeviceMessageConnector
+            .createDeviceMessageTopic(registry, message)
+            .flatMap(topic -> {
                 Mono<Void> publisher = eventBus.publish(topic, message).then();
                 Mono<Void> publisher = eventBus.publish(topic, message).then();
-
                 if (message instanceof ChildDeviceMessage) {
                 if (message instanceof ChildDeviceMessage) {
-                    DeviceMessage msg = (DeviceMessage) ((ChildDeviceMessage) message).getChildDeviceMessage();
-                    publisher = publisher.then(doPublish(registry.getDevice(msg.getDeviceId()), msg));
+                    publisher = publisher.then(doPublish(((ChildDeviceMessage) message).getChildDeviceMessage()));
                 }
                 }
                 return publisher;
                 return publisher;
-            });
+            })
+            .then();
+    }
+
+    @Override
+    public <R extends DeviceMessage> Flux<R> afterSent(DeviceOperator device, DeviceMessage message, Flux<R> reply) {
+        if (message instanceof WritePropertyMessage) {
+            Map<String, Object> properties =((WritePropertyMessage) message).getProperties();
+            if (properties.size() == 1) {
+                String property = properties.keySet().iterator().next();
+                Object value = properties.values().iterator().next();
+                //手动写值的属性则直接返回
+                return device
+                    .getMetadata()
+                    .flatMap(metadata -> Mono
+                        .justOrEmpty(
+                            metadata
+                                .getProperty(property)
+                                .filter(PropertyMetadataConstants.Source::isManual)
+                                .map(ignore -> ((WritePropertyMessage) message)
+                                    .newReply()
+                                    .addHeader("source", PropertyMetadataConstants.Source.manual)
+                                    .addProperty(property, value)
+                                    .success()
+                                )
+                        ))
+                    .map(replyMsg -> this.doPublish(replyMsg).thenReturn((R) replyMsg).flux())
+                    .defaultIfEmpty(reply)
+                    .flatMapMany(Function.identity());
+            }
+        }
+        return reply;
     }
     }
 
 
     @Override
     @Override
     public Mono<DeviceMessage> preSend(DeviceOperator device, DeviceMessage message) {
     public Mono<DeviceMessage> preSend(DeviceOperator device, DeviceMessage message) {
-        return doPublish(Mono.just(device), message)
+        return this
+            .doPublish(message )
             .thenReturn(message)
             .thenReturn(message)
             .doOnEach(ReactiveLogger.onComplete(() -> {
             .doOnEach(ReactiveLogger.onComplete(() -> {
                 if (log.isDebugEnabled()) {
                 if (log.isDebugEnabled()) {