Przeglądaj źródła

Merge remote-tracking branch 'origin/master'

zhouhao 4 lat temu
rodzic
commit
11abcb6834
43 zmienionych plików z 264 dodań i 121 usunięć
  1. 1 1
      README.md
  2. 1 1
      docker/run-all/docker-compose.yml
  3. 1 1
      jetlinks-components/common-component/pom.xml
  4. 63 15
      jetlinks-components/common-component/src/main/java/org/jetlinks/community/Interval.java
  5. 1 1
      jetlinks-components/common-component/src/main/java/org/jetlinks/community/Version.java
  6. 1 1
      jetlinks-components/dashboard-component/pom.xml
  7. 1 1
      jetlinks-components/elasticsearch-component/pom.xml
  8. 7 7
      jetlinks-components/elasticsearch-component/src/main/java/org/jetlinks/community/elastic/search/service/reactive/ReactiveAggregationService.java
  9. 1 1
      jetlinks-components/gateway-component/pom.xml
  10. 1 1
      jetlinks-components/io-component/pom.xml
  11. 1 1
      jetlinks-components/logging-component/pom.xml
  12. 1 1
      jetlinks-components/network-component/mqtt-component/pom.xml
  13. 1 1
      jetlinks-components/network-component/network-core/pom.xml
  14. 1 1
      jetlinks-components/network-component/pom.xml
  15. 1 1
      jetlinks-components/network-component/tcp-component/pom.xml
  16. 1 1
      jetlinks-components/notify-component/notify-core/pom.xml
  17. 1 1
      jetlinks-components/notify-component/notify-dingtalk/pom.xml
  18. 1 1
      jetlinks-components/notify-component/notify-email/pom.xml
  19. 1 1
      jetlinks-components/notify-component/notify-sms/pom.xml
  20. 1 1
      jetlinks-components/notify-component/notify-voice/pom.xml
  21. 1 1
      jetlinks-components/notify-component/notify-wechat/pom.xml
  22. 1 1
      jetlinks-components/notify-component/pom.xml
  23. 1 1
      jetlinks-components/pom.xml
  24. 1 1
      jetlinks-components/rule-engine-component/pom.xml
  25. 1 1
      jetlinks-components/timeseries-component/pom.xml
  26. 1 1
      jetlinks-manager/authentication-manager/pom.xml
  27. 1 1
      jetlinks-manager/device-manager/pom.xml
  28. 1 1
      jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/entity/DeviceInstanceEntity.java
  29. 17 0
      jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/entity/DeviceTagEntity.java
  30. 6 0
      jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/response/DeviceDetail.java
  31. 2 2
      jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DeviceMessageBusinessHandler.java
  32. 112 4
      jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/DeviceInstanceController.java
  33. 14 0
      jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/ProtocolSupportController.java
  34. 1 1
      jetlinks-manager/logging-manager/pom.xml
  35. 1 1
      jetlinks-manager/network-manager/pom.xml
  36. 1 1
      jetlinks-manager/notify-manager/pom.xml
  37. 1 1
      jetlinks-manager/pom.xml
  38. 1 1
      jetlinks-manager/rule-engine-manager/pom.xml
  39. 1 1
      jetlinks-manager/rule-engine-manager/src/main/java/org/jetlinks/community/rule/engine/entity/RuleInstanceEntity.java
  40. 1 1
      jetlinks-manager/visualization-manager/pom.xml
  41. 1 37
      jetlinks-standalone/pom.xml
  42. 4 18
      jetlinks-standalone/src/main/java/org/jetlinks/community/standalone/configuration/protocol/AutoDownloadJarProtocolSupportLoader.java
  43. 5 5
      pom.xml

+ 1 - 1
README.md

@@ -1,7 +1,7 @@
 # JetLinks 物联网基础平台
 
 ![GitHub Workflow Status](https://img.shields.io/github/workflow/status/jetlinks/jetlinks-community/Auto%20Deploy%20Docker?label=docker)
-![Version](https://img.shields.io/badge/Version-1.7--RELEASE-brightgreen)
+![Version](https://img.shields.io/badge/Version-1.8--RELEASE-brightgreen)
 ![QQ群2021514](https://img.shields.io/badge/QQ群-2021514-brightgreen)
 ![jetlinks](https://visitor-badge.glitch.me/badge?page_id=jetlinks)
 

+ 1 - 1
docker/run-all/docker-compose.yml

@@ -59,7 +59,7 @@ services:
     links:
       - jetlinks:jetlinks
   jetlinks:
-    image: registry.cn-shenzhen.aliyuncs.com/jetlinks/jetlinks-standalone:1.8.0-SNAPSHOT
+    image: registry.cn-shenzhen.aliyuncs.com/jetlinks/jetlinks-standalone:1.8.0
     container_name: jetlinks-ce
     ports:
       - 8848:8848 # API端口

+ 1 - 1
jetlinks-components/common-component/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>jetlinks-components</artifactId>
         <groupId>org.jetlinks.community</groupId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 63 - 15
jetlinks-components/common-component/src/main/java/org/jetlinks/community/Interval.java

@@ -1,26 +1,37 @@
 package org.jetlinks.community;
 
+import com.alibaba.fastjson.annotation.JSONType;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.SneakyThrows;
 
 import java.math.BigDecimal;
 
 @Getter
 @AllArgsConstructor
+@NoArgsConstructor
+@JsonDeserialize(using = Interval.IntervalJSONDeserializer.class)
+@JSONType(deserializer = Interval.IntervalJSONDeserializer.class)
 public class Interval {
 
-    public static String year = "y";
-    public static String quarter = "q";
-    public static String month = "M";
-    public static String weeks = "w";
-    public static String days = "d";
-    public static String hours = "h";
-    public static String minutes = "m";
-    public static String seconds = "s";
+    public static final String year = "y";
+    public static final String quarter = "q";
+    public static final String month = "M";
+    public static final String weeks = "w";
+    public static final String days = "d";
+    public static final String hours = "h";
+    public static final String minutes = "m";
+    public static final String seconds = "s";
 
-    private final BigDecimal number;
+    private BigDecimal number;
 
-    private final String expression;
+    private String expression;
 
     public boolean isFixed() {
         return expression.equalsIgnoreCase(hours) ||
@@ -61,18 +72,55 @@ public class Interval {
 
     public static Interval of(String expr) {
 
-        char[] number = new char[32];
+        char[] chars = expr.toCharArray();
         int numIndex = 0;
         for (char c : expr.toCharArray()) {
             if (c == '-' || c == '.' || (c >= '0' && c <= '9')) {
-                number[numIndex++] = c;
-                continue;
+                numIndex++;
+            } else {
+                BigDecimal val = new BigDecimal(chars, 0, numIndex);
+                return new Interval(val, expr.substring(numIndex));
             }
-            BigDecimal val = new BigDecimal(number, 0, numIndex);
-            return new Interval(val, expr.substring(numIndex));
+
         }
 
         throw new IllegalArgumentException("can not parse interval expression:" + expr);
     }
 
+    public String getDefaultFormat() {
+        switch (getExpression()) {
+            case year:
+                return "yyyy";
+            case quarter:
+            case month:
+                return "yyyy-MM";
+            case days:
+                return "yyyy-MM-dd";
+            case hours:
+                return "MM-dd HH";
+            case minutes:
+                return "MM-dd HH:mm";
+            case seconds:
+                return "HH:mm:ss";
+            default:
+                return "yyyy-MM-dd HH:mm:ss";
+        }
+    }
+
+    public static class IntervalJSONDeserializer extends JsonDeserializer<Interval> {
+
+        @Override
+        @SneakyThrows
+        public Interval deserialize(JsonParser jp, DeserializationContext ctxt) {
+            JsonNode node = jp.getCodec().readTree(jp);
+
+            String currentName = jp.currentName();
+            Object currentValue = jp.getCurrentValue();
+            if (currentName == null || currentValue == null) {
+                return null;
+            }
+            return of(node.textValue());
+        }
+    }
+
 }

+ 1 - 1
jetlinks-components/common-component/src/main/java/org/jetlinks/community/Version.java

@@ -8,6 +8,6 @@ public class Version {
 
     private final String edition = "community";
 
-    private final String version = "1.8.0-SNAPSHOT";
+    private final String version = "1.8.0";
 
 }

+ 1 - 1
jetlinks-components/dashboard-component/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>jetlinks-components</artifactId>
         <groupId>org.jetlinks.community</groupId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
jetlinks-components/elasticsearch-component/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>jetlinks-components</artifactId>
         <groupId>org.jetlinks.community</groupId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 7 - 7
jetlinks-components/elasticsearch-component/src/main/java/org/jetlinks/community/elastic/search/service/reactive/ReactiveAggregationService.java

@@ -88,17 +88,17 @@ public class ReactiveAggregationService implements AggregationService {
             builder.timeZone(ZoneId.systemDefault());
             builder.order(BucketOrder.key(false));
             if (timeGroup.getInterval() != null) {
+                Interval interval = timeGroup.getInterval();
+                String intervalString = interval.toString();
                 if (restClient.serverVersion().after(Version.V_7_2_0)) {
-                    Interval interval = timeGroup.getInterval();
-                    if (interval.isFixed()) {
-                        builder.fixedInterval(new DateHistogramInterval(timeGroup.getInterval().toString()));
-                    } else if (interval.isCalendar()) {
-                        builder.calendarInterval(new DateHistogramInterval(timeGroup.getInterval().toString()));
+                    if (DateHistogramAggregationBuilder.DATE_FIELD_UNITS.containsKey(intervalString)) {
+                        builder.calendarInterval(new DateHistogramInterval(intervalString));
                     } else {
-                        builder.dateHistogramInterval(new DateHistogramInterval(timeGroup.getInterval().toString()));
+                        builder.fixedInterval(new DateHistogramInterval(intervalString));
+//                        builder.dateHistogramInterval(new DateHistogramInterval(intervalString));
                     }
                 } else {
-                    builder.dateHistogramInterval(new DateHistogramInterval(timeGroup.getInterval().toString()));
+                    builder.dateHistogramInterval(new DateHistogramInterval(intervalString));
                 }
             }
 

+ 1 - 1
jetlinks-components/gateway-component/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>jetlinks-components</artifactId>
         <groupId>org.jetlinks.community</groupId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
jetlinks-components/io-component/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>jetlinks-components</artifactId>
         <groupId>org.jetlinks.community</groupId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
     </parent>
 
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
jetlinks-components/logging-component/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>jetlinks-components</artifactId>
         <groupId>org.jetlinks.community</groupId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
jetlinks-components/network-component/mqtt-component/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>network-component</artifactId>
         <groupId>org.jetlinks.community</groupId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
jetlinks-components/network-component/network-core/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>network-component</artifactId>
         <groupId>org.jetlinks.community</groupId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
jetlinks-components/network-component/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>jetlinks-components</artifactId>
         <groupId>org.jetlinks.community</groupId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <packaging>pom</packaging>

+ 1 - 1
jetlinks-components/network-component/tcp-component/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>network-component</artifactId>
         <groupId>org.jetlinks.community</groupId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
jetlinks-components/notify-component/notify-core/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>notify-component</artifactId>
         <groupId>org.jetlinks.community</groupId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
jetlinks-components/notify-component/notify-dingtalk/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>notify-component</artifactId>
         <groupId>org.jetlinks.community</groupId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
jetlinks-components/notify-component/notify-email/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>notify-component</artifactId>
         <groupId>org.jetlinks.community</groupId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
jetlinks-components/notify-component/notify-sms/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>notify-component</artifactId>
         <groupId>org.jetlinks.community</groupId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
jetlinks-components/notify-component/notify-voice/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>notify-component</artifactId>
         <groupId>org.jetlinks.community</groupId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
jetlinks-components/notify-component/notify-wechat/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>notify-component</artifactId>
         <groupId>org.jetlinks.community</groupId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
jetlinks-components/notify-component/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>jetlinks-components</artifactId>
         <groupId>org.jetlinks.community</groupId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
jetlinks-components/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>jetlinks-community</artifactId>
         <groupId>org.jetlinks.community</groupId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
jetlinks-components/rule-engine-component/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>jetlinks-components</artifactId>
         <groupId>org.jetlinks.community</groupId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
jetlinks-components/timeseries-component/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>jetlinks-components</artifactId>
         <groupId>org.jetlinks.community</groupId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
jetlinks-manager/authentication-manager/pom.xml

@@ -7,7 +7,7 @@
     <parent>
         <groupId>org.jetlinks.community</groupId>
         <artifactId>jetlinks-manager</artifactId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>authentication-manager</artifactId>

+ 1 - 1
jetlinks-manager/device-manager/pom.xml

@@ -7,7 +7,7 @@
     <parent>
         <groupId>org.jetlinks.community</groupId>
         <artifactId>jetlinks-manager</artifactId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>device-manager</artifactId>

+ 1 - 1
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/entity/DeviceInstanceEntity.java

@@ -76,7 +76,7 @@ public class DeviceInstanceEntity extends GenericEntity<String> implements Recor
     @Schema(description = "派生物模型(预留)")
     private String deriveMetadata;
 
-    @Column(name = "state")
+    @Column(name = "state",length = 16)
     @EnumCodec
     @ColumnType(javaType = String.class)
     @DefaultValue("notActive")

+ 17 - 0
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/entity/DeviceTagEntity.java

@@ -11,6 +11,8 @@ import org.hswebframework.web.api.crud.entity.GenericEntity;
 import org.hswebframework.web.crud.annotation.EnableEntityEvent;
 import org.hswebframework.web.crud.generator.Generators;
 import org.hswebframework.web.validator.CreateGroup;
+import org.jetlinks.core.metadata.Converter;
+import org.jetlinks.core.metadata.DataType;
 import org.jetlinks.core.metadata.PropertyMetadata;
 
 import javax.persistence.Column;
@@ -73,6 +75,21 @@ public class DeviceTagEntity extends GenericEntity<String> {
         return entity;
     }
 
+    public static DeviceTagEntity of(PropertyMetadata property, Object value) {
+        DeviceTagEntity tag = of(property);
+
+        DataType type = property.getValueType();
+        if (type instanceof Converter) {
+            Object newValue = ((Converter<?>) type).convert(value);
+            if (newValue != null) {
+                value = newValue;
+            }
+        }
+        tag.setValue(String.valueOf(value));
+        return tag;
+    }
+
+
     public static String createTagId(String deviceId, String key) {
         return DigestUtils.md5Hex(deviceId + ":" + key);
     }

+ 6 - 0
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/response/DeviceDetail.java

@@ -5,6 +5,7 @@ import lombok.Getter;
 import lombok.Setter;
 import org.apache.commons.collections4.MapUtils;
 import org.jetlinks.community.device.enums.DeviceType;
+import org.jetlinks.core.Values;
 import org.jetlinks.core.device.DeviceOperator;
 import org.jetlinks.community.device.entity.DeviceInstanceEntity;
 import org.jetlinks.community.device.entity.DeviceProductEntity;
@@ -116,6 +117,9 @@ public class DeviceDetail {
     @Schema(description = "标签信息")
     private List<DeviceTagEntity> tags = new ArrayList<>();
 
+    @Schema(description = "设备描述")
+    private String description;
+
     public DeviceDetail notActive() {
 
         state = DeviceState.notActive;
@@ -138,6 +142,7 @@ public class DeviceDetail {
                                             .stream()
                                             .map(ConfigPropertyMetadata::getProperty)
                                             .collect(Collectors.toList()))
+                         .defaultIfEmpty(Values.of(Collections.emptyMap()))
             )
             .doOnNext(tp -> {
                 setOnlineTime(tp.getT2());
@@ -205,6 +210,7 @@ public class DeviceDetail {
         setState(device.getState());
         setOrgId(device.getOrgId());
         setParentId(device.getParentId());
+        setDescription(device.getDescribe());
         Optional.ofNullable(device.getRegistryTime())
                 .ifPresent(this::setRegisterTime);
 

+ 2 - 2
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DeviceMessageBusinessHandler.java

@@ -163,7 +163,7 @@ public class DeviceMessageBusinessHandler {
                 .map(e -> {
                     DeviceTagEntity tagEntity = metadata
                         .getTag(e.getKey())
-                        .map(DeviceTagEntity::of)
+                        .map(tagMeta -> DeviceTagEntity.of(tagMeta, e.getValue()))
                         .orElseGet(() -> {
                             DeviceTagEntity entity = new DeviceTagEntity();
                             entity.setKey(e.getKey());
@@ -171,9 +171,9 @@ public class DeviceMessageBusinessHandler {
                             entity.setName(e.getKey());
                             entity.setCreateTime(new Date());
                             entity.setDescription("设备上报");
+                            entity.setValue(String.valueOf(e.getValue()));
                             return entity;
                         });
-                    tagEntity.setValue(String.valueOf(e.getValue()));
                     tagEntity.setDeviceId(deviceId);
                     tagEntity.setId(DeviceTagEntity.createTagId(deviceId, tagEntity.getKey()));
                     return tagEntity;

+ 112 - 4
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/DeviceInstanceController.java

@@ -19,7 +19,9 @@ import org.hswebframework.web.authorization.annotation.*;
 import org.hswebframework.web.bean.FastBeanCopier;
 import org.hswebframework.web.crud.web.reactive.ReactiveServiceCrudController;
 import org.hswebframework.web.exception.BusinessException;
+import org.hswebframework.web.exception.NotFoundException;
 import org.hswebframework.web.exception.ValidationException;
+import org.hswebframework.web.id.IDGenerator;
 import org.jetlinks.community.device.entity.*;
 import org.jetlinks.community.device.enums.DeviceState;
 import org.jetlinks.community.device.response.DeviceDeployResult;
@@ -37,17 +39,20 @@ import org.jetlinks.community.io.utils.FileUtils;
 import org.jetlinks.community.timeseries.query.AggregationData;
 import org.jetlinks.core.ProtocolSupport;
 import org.jetlinks.core.Values;
-import org.jetlinks.core.device.DeviceConfigKey;
-import org.jetlinks.core.device.DeviceOperator;
-import org.jetlinks.core.device.DeviceProductOperator;
-import org.jetlinks.core.device.DeviceRegistry;
+import org.jetlinks.core.device.*;
 import org.jetlinks.core.device.manager.DeviceBindHolder;
 import org.jetlinks.core.device.manager.DeviceBindProvider;
+import org.jetlinks.core.exception.DeviceOperationException;
+import org.jetlinks.core.message.DeviceMessage;
+import org.jetlinks.core.message.Message;
+import org.jetlinks.core.message.MessageType;
+import org.jetlinks.core.message.RepayableDeviceMessage;
 import org.jetlinks.core.metadata.ConfigMetadata;
 import org.jetlinks.core.metadata.ConfigPropertyMetadata;
 import org.jetlinks.core.metadata.DeviceMetadata;
 import org.springframework.core.io.buffer.DataBufferFactory;
 import org.springframework.core.io.buffer.DefaultDataBufferFactory;
+import org.springframework.data.util.Lazy;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.MediaType;
 import org.springframework.http.server.reactive.ServerHttpResponse;
@@ -64,6 +69,7 @@ import java.io.IOException;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.function.Function;
@@ -630,4 +636,106 @@ public class DeviceInstanceController implements
             .map(AggregationData::values);
     }
 
+    //发送设备指令
+    @PostMapping("/{deviceId:.+}/message")
+    @SneakyThrows
+    @QueryAction
+    @Operation(summary = "发送指令到设备")
+    @SuppressWarnings("all")
+    public Flux<?> sendMessage(@PathVariable @Parameter(description = "设备ID") String deviceId,
+                               @RequestBody Mono<Map<String, Object>> properties) {
+        return properties
+            .flatMapMany(props -> {
+                return Mono
+                    .zip(
+                        registry
+                            .getDevice(deviceId)
+                            .map(DeviceOperator::messageSender)
+                            .switchIfEmpty(Mono.error(() -> new NotFoundException("设备不存在或未激活"))),
+                        Mono.<Message>justOrEmpty(MessageType.convertMessage(props))
+                            .cast(DeviceMessage.class)
+                            .switchIfEmpty(Mono.error(() -> new UnsupportedOperationException("不支持的消息格式")))
+                    ).flatMapMany(tp2 -> {
+                        DeviceMessageSender sender = tp2.getT1();
+                        DeviceMessage message = tp2.getT2();
+
+                        Map<String, String> copy = new HashMap<>();
+                        copy.put("deviceId", deviceId);
+                        if (!StringUtils.hasText(message.getMessageId())) {
+                            copy.put("messageId", IDGenerator.SNOW_FLAKE_STRING.generate());
+                        }
+                        FastBeanCopier.copy(copy, message);
+                        return sender
+                            .send(message)
+                            .onErrorResume(DeviceOperationException.class, error -> {
+                                if (message instanceof RepayableDeviceMessage) {
+                                    return Mono.just(
+                                        ((RepayableDeviceMessage) message).newReply().error(error)
+                                    );
+                                }
+                                return Mono.error(error);
+                            });
+                    });
+            });
+    }
+
+    //发送设备指令
+    @PostMapping("/messages")
+    @SneakyThrows
+    @QueryAction
+    @Operation(summary = "批量发送指令到设备")
+    @SuppressWarnings("all")
+    public Flux<?> sendMessage(@RequestParam(required = false)
+                               @Parameter(description = "按查询条件发送指令") String where,
+                               @RequestBody Flux<Map<String, Object>> messages) {
+
+        Lazy<Flux<DeviceOperator>> operators = Lazy.of(() -> {
+            if (StringUtils.isEmpty(where)) {
+                throw new ValidationException("where", "[where]参数不能为空");
+            }
+            QueryParamEntity entity = new QueryParamEntity();
+            entity.setWhere(where);
+            entity.includes("id");
+            return service.query(entity)
+                          .flatMap(device -> registry.getDevice(device.getId()))
+                          .cache();
+        });
+        return messages
+            .flatMap(message -> {
+                DeviceMessage msg = MessageType
+                    .convertMessage(message)
+                    .filter(DeviceMessage.class::isInstance)
+                    .map(DeviceMessage.class::cast)
+                    .orElseThrow(() -> new UnsupportedOperationException("不支持的消息格式:" + message));
+
+                String deviceId = msg.getDeviceId();
+                Flux<DeviceOperator> devices = StringUtils.isEmpty(deviceId)
+                    ? operators.get()
+                    : registry.getDevice(deviceId).flux();
+
+                return devices
+                    .flatMap(device -> {
+                        Map<String, Object> copy = new HashMap<>(message);
+                        copy.put("deviceId", device.getDeviceId());
+                        copy.putIfAbsent("messageId", IDGenerator.SNOW_FLAKE_STRING.generate());
+                        //复制为新的消息,防止冲突
+                        DeviceMessage copiedMessage = MessageType
+                            .convertMessage(copy)
+                            .map(DeviceMessage.class::cast)
+                            .orElseThrow(() -> new UnsupportedOperationException("不支持的消息格式"));
+                        return device
+                            .messageSender()
+                            .send(copiedMessage)
+                            .onErrorResume(Exception.class, error -> {
+                                if (copiedMessage instanceof RepayableDeviceMessage) {
+                                    return Mono.just(
+                                        ((RepayableDeviceMessage) copiedMessage).newReply().error(error)
+                                    );
+                                }
+                                return Mono.error(error);
+                            });
+                    });
+            });
+    }
+
 }

+ 14 - 0
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/ProtocolSupportController.java

@@ -102,6 +102,20 @@ public class ProtocolSupportController
             .flatMap(support -> support.getConfigMetadata(transport));
     }
 
+    @GetMapping("/{id}/{transport}/metadata")
+    @QueryAction
+    @Authorize(merge = false)
+    @Operation(summary = "获取协议设置的默认物模型")
+    public Mono<String> getDefaultMetadata(@PathVariable @Parameter(description = "协议ID") String id,
+                                           @PathVariable @Parameter(description = "传输协议") DefaultTransport transport) {
+        return protocolSupports
+            .getProtocol(id)
+            .flatMap(support ->support
+                .getDefaultMetadata(transport)
+                .flatMap(metadata-> support.getMetadataCodec().encode(metadata))
+            ).defaultIfEmpty("{}");
+    }
+
     @GetMapping("/{id}/transports")
     @Authorize(merge = false)
     @Operation(summary = "获取协议支持的传输协议")

+ 1 - 1
jetlinks-manager/logging-manager/pom.xml

@@ -7,7 +7,7 @@
     <parent>
         <groupId>org.jetlinks.community</groupId>
         <artifactId>jetlinks-manager</artifactId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
     </parent>
     <artifactId>logging-manager</artifactId>
 

+ 1 - 1
jetlinks-manager/network-manager/pom.xml

@@ -7,7 +7,7 @@
     <parent>
         <groupId>org.jetlinks.community</groupId>
         <artifactId>jetlinks-manager</artifactId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>network-manager</artifactId>

+ 1 - 1
jetlinks-manager/notify-manager/pom.xml

@@ -7,7 +7,7 @@
     <parent>
         <groupId>org.jetlinks.community</groupId>
         <artifactId>jetlinks-manager</artifactId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>notify-manager</artifactId>

+ 1 - 1
jetlinks-manager/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>jetlinks-community</artifactId>
         <groupId>org.jetlinks.community</groupId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
     </parent>
     <packaging>pom</packaging>
     <modelVersion>4.0.0</modelVersion>

+ 1 - 1
jetlinks-manager/rule-engine-manager/pom.xml

@@ -7,7 +7,7 @@
     <parent>
         <groupId>org.jetlinks.community</groupId>
         <artifactId>jetlinks-manager</artifactId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>rule-engine-manager</artifactId>

+ 1 - 1
jetlinks-manager/rule-engine-manager/src/main/java/org/jetlinks/community/rule/engine/entity/RuleInstanceEntity.java

@@ -67,7 +67,7 @@ public class RuleInstanceEntity extends GenericEntity<String> implements RecordC
     @Schema(description = "创建者ID")
     private String creatorId;
 
-    @Column(name = "state")
+    @Column(name = "state",length = 16)
     @EnumCodec
     @ColumnType(javaType = String.class)
     @DefaultValue("stopped")

+ 1 - 1
jetlinks-manager/visualization-manager/pom.xml

@@ -7,7 +7,7 @@
     <parent>
         <groupId>org.jetlinks.community</groupId>
         <artifactId>jetlinks-manager</artifactId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <artifactId>visualization-manager</artifactId>

+ 1 - 37
jetlinks-standalone/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>jetlinks-community</artifactId>
         <groupId>org.jetlinks.community</groupId>
-        <version>1.8.0-SNAPSHOT</version>
+        <version>1.8.0</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>
@@ -49,41 +49,6 @@
                 </executions>
             </plugin>
 
-            <plugin>
-                <groupId>com.spotify</groupId>
-                <artifactId>docker-maven-plugin</artifactId>
-                <version>1.2.0</version>
-                <configuration>
-                    <imageName>${docker.image.name}</imageName>
-                    <imageTags>
-                        <imageTag>${project.version}</imageTag>
-                    </imageTags>
-                    <baseImage>openjdk:8</baseImage>
-                    <workdir>/</workdir>
-                    <env>
-                        <TZ>Asia/Shanghai</TZ>
-                        <APP_JAR>/${project.build.finalName}.jar</APP_JAR>
-                    </env>
-                    <runs>
-                        <run>chmod +x docker-entrypoint.sh</run>
-                    </runs>
-                    <entryPoint>["/docker-entrypoint.sh"]</entryPoint>
-                    <resources>
-                        <resource>
-                            <targetPath>/</targetPath>
-                            <directory>${project.basedir}</directory>
-                            <include>docker-entrypoint.sh</include>
-                        </resource>
-                        <resource>
-                            <targetPath>/</targetPath>
-                            <directory>${project.build.directory}</directory>
-                            <include>${project.build.finalName}.jar</include>
-                        </resource>
-                    </resources>
-                    <serverId>docker-repo</serverId>
-                </configuration>
-            </plugin>
-
         </plugins>
     </build>
 
@@ -115,7 +80,6 @@
         <dependency>
             <groupId>io.projectreactor.netty</groupId>
             <artifactId>reactor-netty</artifactId>
-            <version>0.9.10.RELEASE</version>
             <scope>compile</scope>
         </dependency>
 

+ 4 - 18
jetlinks-standalone/src/main/java/org/jetlinks/community/standalone/configuration/protocol/AutoDownloadJarProtocolSupportLoader.java

@@ -96,24 +96,10 @@ public class AutoDownloadJarProtocolSupportLoader extends JarProtocolSupportLoad
                 .retrieve()
                 .bodyToFlux(DataBuffer.class)
                 .as(dataStream -> {
-                    Path filePath = file.toPath();
-                    log.debug("write protocol file {} to {}", location, file.getAbsolutePath());
-                    try {
-                        @SuppressWarnings("all")
-                        AsynchronousFileChannel asynchronousFileChannel = AsynchronousFileChannel.open(filePath, CREATE,WRITE);
-                        return DataBufferUtils
-                            .write(dataStream, asynchronousFileChannel)
-                            .doOnNext(DataBufferUtils.releaseConsumer())
-                            .doAfterTerminate(() -> {
-                                try {
-                                    asynchronousFileChannel.close();
-                                } catch (IOException ignored) {
-                                }
-                            })
-                            .then(Mono.just(file.getAbsolutePath()));
-                    } catch (Exception e) {
-                        throw new RuntimeException(e);
-                    }
+                    log.debug("download protocol file {} to {}", location, file.getAbsolutePath());
+                    return DataBufferUtils
+                        .write(dataStream, file.toPath(), CREATE, WRITE)
+                        .thenReturn(file.getAbsolutePath());
                 })
                 .subscribeOn(Schedulers.elastic())
                 .doOnNext(path -> config.put("location", path))

+ 5 - 5
pom.xml

@@ -6,7 +6,7 @@
 
     <groupId>org.jetlinks.community</groupId>
     <artifactId>jetlinks-community</artifactId>
-    <version>1.8.0-SNAPSHOT</version>
+    <version>1.8.0</version>
     <modules>
         <module>jetlinks-components</module>
         <module>jetlinks-manager</module>
@@ -16,13 +16,13 @@
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.build.locales>zh_CN</project.build.locales>
-        <spring.boot.version>2.3.4.RELEASE</spring.boot.version>
+        <spring.boot.version>2.3.8.RELEASE</spring.boot.version>
         <java.version>1.8</java.version>
         <project.build.jdk>${java.version}</project.build.jdk>
-        <hsweb.framework.version>4.0.9-SNAPSHOT</hsweb.framework.version>
-        <easyorm.version>4.0.9-SNAPSHOT</easyorm.version>
+        <hsweb.framework.version>4.0.9</hsweb.framework.version>
+        <easyorm.version>4.0.9</easyorm.version>
         <hsweb.expands.version>3.0.2</hsweb.expands.version>
-        <jetlinks.version>1.1.5-SNAPSHOT</jetlinks.version>
+        <jetlinks.version>1.1.5</jetlinks.version>
         <r2dbc.version>Arabba-SR7</r2dbc.version>
         <vertx.version>3.8.5</vertx.version>
         <netty.version>4.1.51.Final</netty.version>