Browse Source

add 地理位置

18339543638 4 years ago
parent
commit
b51062fa84
13 changed files with 244 additions and 107 deletions
  1. 14 4
      jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/configuration/GeoIndexInitialize.java
  2. 1 1
      jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/configuration/GeoIndexProvider.java
  3. 16 0
      jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/constant/GeoConstant.java
  4. 34 0
      jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/dto/DeviceGeoDto.java
  5. 10 0
      jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/entity/DeviceInstanceEntity.java
  6. 12 0
      jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/entity/DeviceTagEntity.java
  7. 32 0
      jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/entity/DeviceTagGeoInfo.java
  8. 27 1
      jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/entity/geo/GeoProperty.java
  9. 5 3
      jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/response/DeviceDetail.java
  10. 7 44
      jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DeviceTagsService.java
  11. 0 21
      jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/GeoDataSaveService.java
  12. 72 28
      jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/DeviceInstanceController.java
  13. 14 5
      jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/GeoController.java

+ 14 - 4
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/configuration/GeoIndexInitialize.java

@@ -1,12 +1,16 @@
 package org.jetlinks.community.device.configuration;
 
+import org.jetlinks.community.device.constant.GeoConstant;
 import org.jetlinks.community.elastic.search.index.DefaultElasticSearchIndexMetadata;
 import org.jetlinks.community.elastic.search.index.ElasticSearchIndexManager;
 import org.jetlinks.community.elastic.search.index.strategies.DirectElasticSearchIndexStrategy;
+import org.jetlinks.core.metadata.types.GeoType;
 import org.jetlinks.core.metadata.types.StringType;
 import org.springframework.core.annotation.Order;
 import org.springframework.stereotype.Component;
 
+import javax.annotation.PostConstruct;
+
 /**
  * @author lifang
  * @version 1.0.0
@@ -17,10 +21,16 @@ import org.springframework.stereotype.Component;
 @Component
 @Order(1)
 public class GeoIndexInitialize {
-    public GeoIndexInitialize(DirectElasticSearchIndexStrategy indexManager) {
-        indexManager.putIndex(new DefaultElasticSearchIndexMetadata(GeoIndexProvider.GEO_TAG.getIndex())
-            .addProperty("deviceId", new StringType())
-            .addProperty("location", new StringType()))
+
+    public GeoIndexInitialize(ElasticSearchIndexManager indexManager) {
+        indexManager.useStrategy(GeoIndexProvider.GEO.getIndex().toLowerCase(),"direct");
+        indexManager.putIndex(new DefaultElasticSearchIndexMetadata(GeoIndexProvider.GEO.getIndex())
+            .addProperty(GeoConstant.ES_DEVICE_ID, new StringType())
+            .addProperty(GeoConstant.ES_DEVICE_NAME, new StringType())
+            .addProperty(GeoConstant.ES_DEVICE_PRODUCT_ID,new StringType())
+            .addProperty(GeoConstant.ES_DEVICE_PRODUCT_NAME, new StringType())
+            .addProperty(GeoConstant.ES_DEVICE_GEO_POINT, new GeoType()))
             .subscribe();
     }
+
 }

+ 1 - 1
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/configuration/GeoIndexProvider.java

@@ -8,7 +8,7 @@ import org.jetlinks.community.elastic.search.index.ElasticIndex;
 @AllArgsConstructor
 public enum GeoIndexProvider implements ElasticIndex {
 
-    GEO_TAG("geo-point-tag", "_doc");
+    GEO("device-geo-point", "_doc");
 
     private String index;
 

+ 16 - 0
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/constant/GeoConstant.java

@@ -0,0 +1,16 @@
+package org.jetlinks.community.device.constant;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName GeoConstant.java
+ * @Description TODO
+ * @createTime 2021年10月22日 16:55:00
+ */
+public class GeoConstant {
+    public static final String ES_DEVICE_ID="id";
+    public static final String ES_DEVICE_NAME="name";
+    public static final String ES_DEVICE_PRODUCT_ID="productId";
+    public static final String ES_DEVICE_PRODUCT_NAME="productName";
+    public static final String ES_DEVICE_GEO_POINT="coordinate";
+}

+ 34 - 0
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/dto/DeviceGeoDto.java

@@ -0,0 +1,34 @@
+package org.jetlinks.community.device.dto;
+
+import lombok.Data;
+import org.jetlinks.community.device.entity.DeviceInstanceEntity;
+import org.jetlinks.core.metadata.types.GeoPoint;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName DeviceGeoDto.java
+ * @Description TODO
+ * @createTime 2021年10月22日 19:01:00
+ */
+@Data
+public class DeviceGeoDto {
+    private String id;
+
+    private String name;
+
+    private String productId;
+    private String productName;
+
+    private GeoPoint coordinate;
+
+    public static DeviceGeoDto of(DeviceInstanceEntity instanceEntity){
+        DeviceGeoDto deviceGeo = new DeviceGeoDto();
+        deviceGeo.setId(instanceEntity.getId());
+        deviceGeo.setName(instanceEntity.getName());
+        deviceGeo.setProductId(instanceEntity.getProductId());
+        deviceGeo.setProductName(instanceEntity.getProductName());
+        deviceGeo.setCoordinate(instanceEntity.getCoordinate());
+        return deviceGeo;
+    }
+}

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

@@ -13,6 +13,7 @@ import org.jetlinks.community.device.enums.DeviceFeature;
 import org.jetlinks.community.device.enums.DeviceState;
 import org.jetlinks.core.device.DeviceConfigKey;
 import org.jetlinks.core.device.DeviceInfo;
+import org.jetlinks.core.metadata.types.GeoPoint;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
 
@@ -66,6 +67,15 @@ public class DeviceInstanceEntity extends GenericEntity<String> implements Recor
     @Schema(description = "产品名称")
     private String productName;
 
+
+    //todo
+    @Comment("地理位置")
+    @Column(name = "coordinate")
+    @JsonCodec
+    @ColumnType(jdbcType = JDBCType.VARCHAR)
+    @Schema(description = "地理位置")
+    private GeoPoint coordinate;
+
     @Comment("其他配置")
     @Column(name = "configuration")
     @ColumnType(jdbcType = JDBCType.CLOB)

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

@@ -12,6 +12,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.community.device.entity.geo.GeoProperty;
+import org.jetlinks.community.device.entity.geo.Geometry;
 import org.jetlinks.core.metadata.Converter;
 import org.jetlinks.core.metadata.DataType;
 import org.jetlinks.core.metadata.PropertyMetadata;
@@ -118,4 +120,14 @@ public class DeviceTagEntity extends GenericEntity<String> {
     public static String createTagId(String deviceId, String key) {
         return DigestUtils.md5Hex(deviceId + ":" + key);
     }
+
+    public static DeviceTagEntity of(GeoProperty geoProperty){
+        DeviceTagEntity tag = new DeviceTagEntity();
+        Geometry geometry = geoProperty.getGeometry();
+        tag.setKey("coordinate");
+        tag.setValue(geometry.getCoordinates().get(0)+","+geometry.getCoordinates().get(1));
+        tag.setDeviceId(geoProperty.getObjectId());
+        tag.setName("地理位置");
+        return tag;
+    }
 }

+ 32 - 0
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/entity/DeviceTagGeoInfo.java

@@ -0,0 +1,32 @@
+package org.jetlinks.community.device.entity;
+
+import lombok.Data;
+
+import javax.persistence.Column;
+
+/**
+ * @author lifang
+ * @version 1.0.0
+ * @ClassName DeviceTagGeoInfo.java
+ * @Description TODO
+ * @createTime 2021年10月22日 15:29:00
+ */
+@Data
+public class DeviceTagGeoInfo {
+
+    private String deviceId;
+
+    private String deviceName;
+
+    private String productId;
+    private String productName;
+
+    private String locationShape;
+
+    private String locationPoint;
+
+    public static DeviceTagGeoInfo of(DeviceTagEntity tag, DeviceInstanceEntity device){
+        DeviceTagGeoInfo geoProperty = new DeviceTagGeoInfo();
+        return geoProperty;
+    }
+}

+ 27 - 1
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/entity/geo/GeoProperty.java

@@ -5,14 +5,17 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 import org.hswebframework.ezorm.rdb.mapping.annotation.ColumnType;
 import org.hswebframework.ezorm.rdb.mapping.annotation.JsonCodec;
 import org.hswebframework.web.api.crud.entity.GenericEntity;
 import org.hswebframework.web.validator.CreateGroup;
+import org.jetlinks.community.device.entity.DeviceInstanceEntity;
+import org.jetlinks.community.device.entity.DeviceTagEntity;
+import reactor.util.function.Tuple2;
 import javax.persistence.Column;
 import javax.persistence.Index;
 import javax.persistence.Table;
-import javax.persistence.Transient;
 import javax.validation.constraints.NotBlank;
 import java.sql.JDBCType;
 import java.util.*;
@@ -22,6 +25,7 @@ import java.util.*;
     @Index(name = "fromUnique",columnList = "from_id")
 })
 @Data
+@EqualsAndHashCode(callSuper = false)
 public  class GeoProperty extends GenericEntity<String> {
     @Column
     @Schema(description = "属性名称")
@@ -88,4 +92,26 @@ public  class GeoProperty extends GenericEntity<String> {
     @Schema(description = "地图信息")
     private Geometry geometry;
 
+    public static GeoProperty of(DeviceTagEntity tag, DeviceInstanceEntity device){
+        GeoProperty geoProperty = new GeoProperty();
+        Geometry geometry = new Geometry();
+        String[] split = tag.getValue().split(",");
+        geometry.getCoordinates().add(split[0]);
+        geometry.getCoordinates().add(split[1]);
+        geometry.setType("Point");
+        geoProperty.setId(tag.getId());
+//        geoProperty.setFrom("tag");
+//        geoProperty.setFromId(tag.getId());
+        geoProperty.setObjectId(tag.getDeviceId());
+        geoProperty.setObjectType("device");
+        geoProperty.setDeviceName(device.getName());
+        geoProperty.setProductName(device.getProductName());
+        geoProperty.setProductId(device.getProductId());
+        geoProperty.setGeometry(geometry);
+        return geoProperty;
+    }
+
+    public static GeoProperty of(Tuple2<DeviceTagEntity,DeviceInstanceEntity> tp2){
+        return of(tp2.getT1(),tp2.getT2());
+    }
 }

+ 5 - 3
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/response/DeviceDetail.java

@@ -1,6 +1,5 @@
 package org.jetlinks.community.device.response;
 
-import cn.hutool.core.collection.CollectionUtil;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Getter;
 import lombok.Setter;
@@ -10,11 +9,10 @@ import org.jetlinks.community.device.entity.DeviceProductEntity;
 import org.jetlinks.community.device.entity.DeviceTagEntity;
 import org.jetlinks.community.device.enums.DeviceState;
 import org.jetlinks.community.device.enums.DeviceType;
-import org.jetlinks.community.device.enums.GeoType;
 import org.jetlinks.core.Values;
 import org.jetlinks.core.device.DeviceOperator;
 import org.jetlinks.core.metadata.ConfigPropertyMetadata;
-import org.jetlinks.core.metadata.types.GeoShape;
+import org.jetlinks.core.metadata.types.GeoPoint;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
 import reactor.core.publisher.Mono;
@@ -100,6 +98,8 @@ public class DeviceDetail {
     @Schema(description = "物模型")
     private String metadata;
 
+    @Schema(description = "地理位置")
+    private GeoPoint coordinate;
     //是否为独立物模型
     @Schema(description = "是否为独立物模型")
     private boolean independentMetadata;
@@ -175,6 +175,7 @@ public class DeviceDetail {
         geoTag.setDeviceId(this.id);
         geoTag.setType("geoPoint");
         geoTag.setKey("coordinate");
+        geoTag.setDescription("地理位置坐标");
         if (CollectionUtils.isEmpty(tags)) {
             this.tags= Collections.singletonList(geoTag);
             return this;
@@ -222,6 +223,7 @@ public class DeviceDetail {
 
     public DeviceDetail with(DeviceInstanceEntity device) {
 
+        setCoordinate(device.getCoordinate());
         setId(device.getId());
         setName(device.getName());
         setState(device.getState());

+ 7 - 44
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/DeviceTagsService.java

@@ -4,14 +4,15 @@ import lombok.AllArgsConstructor;
 import org.hswebframework.ezorm.rdb.mapping.ReactiveRepository;
 import org.hswebframework.web.crud.service.GenericReactiveCrudService;
 import org.hswebframework.web.exception.BusinessException;
+import org.jetlinks.community.device.configuration.GeoIndexProvider;
 import org.jetlinks.community.device.entity.DeviceTagEntity;
 import org.jetlinks.community.device.entity.geo.GeoProperty;
 import org.jetlinks.community.device.entity.geo.Geometry;
+import org.jetlinks.community.elastic.search.service.ElasticSearchService;
 import org.jetlinks.core.metadata.types.GeoType;
 import org.springframework.stereotype.Service;
 import reactor.core.Disposable;
 import reactor.core.publisher.Mono;
-import reactor.core.scheduler.Schedulers;
 
 /**
  * @author lifang
@@ -27,7 +28,7 @@ public class DeviceTagsService  extends GenericReactiveCrudService<DeviceTagEnti
     private final LocalDeviceInstanceService instanceService;
     private final LocalDeviceProductService productService;
     private final ReactiveRepository<GeoProperty, String> propertyRepository;
-
+    private final ElasticSearchService elasticSearchService;
     public Mono<Void> saveOrUpdate(DeviceTagEntity entity) {
         return
             //先判断是否存在
@@ -55,48 +56,6 @@ public class DeviceTagsService  extends GenericReactiveCrudService<DeviceTagEnti
                             .then();
                     }
                 })
-//                .doOnNext(ignore->{
-//                    if (judgementGeo(entity)) {
-//                        GeoProperty geoProperty = new GeoProperty();
-//                        Geometry geometry = new Geometry();
-//                        String[] split = entity.getValue().split(",");
-//                        geometry.getCoordinates().add(split[0]);
-//                        geometry.getCoordinates().add(split[1]);
-//                        geometry.setType("Point");
-//                        instanceService.findById(entity.getDeviceId())
-//                            .flatMap(device->{
-//                                geoProperty.setFrom("tag");
-//                                geoProperty.setFromId(entity.getId());
-//                                geoProperty.setObjectId(device.getId());
-//                                geoProperty.setObjectType("device");
-//                                geoProperty.setDeviceName(device.getName());
-//                                return productService.findById(device.getProductId());
-//                            })
-//                            .doOnNext(product->{
-//                                geoProperty.setProductName(product.getName());
-//                                geoProperty.setProductId(product.getId());
-//                                geoProperty.setGeometry(geometry);
-//                            })
-//                            .subscribe(ignore0->{
-//                                propertyRepository.createQuery()
-//                                    .where(GeoProperty::getFrom,"tag")
-//                                    .where(GeoProperty::getFromId,entity.getId())
-//                                    .count()
-//                                    .flatMap(count->{
-//                                        if(count==0){
-//                                            return propertyRepository.save(geoProperty);
-//                                        }else {
-//                                            return propertyRepository.createUpdate()
-//                                                .where(GeoProperty::getFrom,"tag")
-//                                                .where(GeoProperty::getFromId,entity.getId())
-//                                                .set(GeoProperty::getGeometry,geometry)
-//                                                .execute();
-//                                        }
-//                                    })
-//                                    .subscribe();
-//                            });
-//                    }
-//                })
                 .then();
     }
 
@@ -145,4 +104,8 @@ public class DeviceTagsService  extends GenericReactiveCrudService<DeviceTagEnti
                     .subscribe();
             });
     }
+
+    public Mono<Void> updateESTagGeo(DeviceTagEntity entity){
+        return elasticSearchService.save(GeoIndexProvider.GEO.getIndex(),Mono.just(entity));
+    }
 }

+ 0 - 21
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/service/GeoDataSaveService.java

@@ -1,21 +0,0 @@
-package org.jetlinks.community.device.service;
-
-import org.jetlinks.core.metadata.types.GeoPoint;
-import reactor.core.publisher.Mono;
-
-/**
- * @author lifang
- * @version 1.0.0
- * @ClassName GeoDataSaveService.java
- * @Description
- * @createTime 2021年10月21日 10:36:00
- */
-public interface GeoDataSaveService {
-    /**
-     * 获取设备地理标签信息
-     * @return
-     */
-    Mono<GeoPoint> getGeoTag(String deviceId);
-
-    Mono<Void> putGeoTag(String deviceId, GeoPoint geoPoint);
-}

+ 72 - 28
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/DeviceInstanceController.java

@@ -1,5 +1,6 @@
 package org.jetlinks.community.device.web;
 
+import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.json.JSONUtil;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
@@ -22,20 +23,19 @@ 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.configuration.GeoIndexProvider;
+import org.jetlinks.community.device.dto.DeviceGeoDto;
 import org.jetlinks.community.device.entity.*;
-import org.jetlinks.community.device.entity.geo.GeoProperty;
 import org.jetlinks.community.device.enums.DeviceState;
 import org.jetlinks.community.device.response.DeviceDeployResult;
 import org.jetlinks.community.device.response.DeviceDetail;
 import org.jetlinks.community.device.response.ImportDeviceInstanceResult;
-import org.jetlinks.community.device.service.DeviceConfigMetadataManager;
-import org.jetlinks.community.device.service.DeviceTagsService;
-import org.jetlinks.community.device.service.LocalDeviceInstanceService;
-import org.jetlinks.community.device.service.LocalDeviceProductService;
+import org.jetlinks.community.device.service.*;
 import org.jetlinks.community.device.service.data.DeviceDataService;
 import org.jetlinks.community.device.web.excel.DeviceExcelInfo;
 import org.jetlinks.community.device.web.excel.DeviceWrapper;
 import org.jetlinks.community.device.web.request.AggRequest;
+import org.jetlinks.community.elastic.search.service.ElasticSearchService;
 import org.jetlinks.community.io.excel.ImportExportService;
 import org.jetlinks.community.io.utils.FileUtils;
 import org.jetlinks.community.timeseries.query.AggregationData;
@@ -49,6 +49,7 @@ import org.jetlinks.core.message.Message;
 import org.jetlinks.core.message.MessageType;
 import org.jetlinks.core.message.RepayableDeviceMessage;
 import org.jetlinks.core.metadata.*;
+import org.jetlinks.core.metadata.types.GeoPoint;
 import org.springframework.core.io.buffer.DataBufferFactory;
 import org.springframework.core.io.buffer.DefaultDataBufferFactory;
 import org.springframework.dao.DuplicateKeyException;
@@ -97,7 +98,9 @@ public class DeviceInstanceController implements
 
     private final DeviceTagsService tagsService;
 
-    private final ReactiveRepository<GeoProperty, String> propertyRepository;
+    private final LocalDeviceInstanceService instanceService;
+
+    private final ElasticSearchService elasticSearchService;
     @SuppressWarnings("all")
     public DeviceInstanceController(LocalDeviceInstanceService service,
                                     DeviceRegistry registry,
@@ -107,7 +110,8 @@ public class DeviceInstanceController implements
                                     DeviceDataService deviceDataService,
                                     DeviceConfigMetadataManager metadataManager,
                                     DeviceTagsService tagsService,
-                                    ReactiveRepository<GeoProperty, String> propertyRepository) {
+                                    LocalDeviceInstanceService instanceService,
+                                    ElasticSearchService elasticSearchService) {
         this.service = service;
         this.registry = registry;
         this.productService = productService;
@@ -116,7 +120,8 @@ public class DeviceInstanceController implements
         this.deviceDataService = deviceDataService;
         this.metadataManager = metadataManager;
         this.tagsService=tagsService;
-        this.propertyRepository=propertyRepository;
+        this.instanceService=instanceService;
+        this.elasticSearchService=elasticSearchService;
     }
 
 
@@ -331,20 +336,11 @@ public class DeviceInstanceController implements
     @Operation(summary = "删除设备标签")
     public Mono<Void> deleteDeviceTag(@PathVariable @Parameter(description = "设备ID") String deviceId,
                                       @PathVariable @Parameter(description = "标签ID") String tagId) {
-        return tagRepository.findById(tagId)
-            .doOnNext(ignore->
-                tagRepository.createDelete()
-                    .where(DeviceTagEntity::getDeviceId, deviceId)
-                    .and(DeviceTagEntity::getId, tagId)
-                    .execute()
-                    .subscribe()
-            ).filter(tagsService::judgementGeo)
-            .doOnNext(tag->
-                propertyRepository
-                    .createDelete()
-                    .where(GeoProperty::getFromId,tagId)
-                    .execute()
-            ).then();
+        return tagRepository.createDelete()
+            .where(DeviceTagEntity::getDeviceId, deviceId)
+            .and(DeviceTagEntity::getId, tagId)
+            .execute()
+            .then();
     }
 
     /**
@@ -423,18 +419,16 @@ public class DeviceInstanceController implements
     //保存设备标签
     @PatchMapping("/{deviceId}/tag")
     @SaveAction
-    @Operation(summary = "保存设备标签")
-    public Flux<DeviceTagEntity> saveDeviceTag(@PathVariable @Parameter(description = "设备ID") String deviceId,
-                                               @RequestBody Flux<DeviceTagEntity> tags) {
+    @Operation(summary = "保存设备标签(地理位置除外)")
+    public Flux<DeviceTagEntity> saveDeviceNormalTag(@PathVariable @Parameter(description = "设备ID") String deviceId,
+                                                     @RequestBody Flux<DeviceTagEntity> tags) {
         return tags
             .doOnNext(tag -> {
                 tag.setId(DeviceTagEntity.createTagId(deviceId, tag.getKey()));
                 tag.setDeviceId(deviceId);
                 tag.tryValidate();
-                tag.setAutoUpdate(true);
             })
-            .flatMap(tagsService::saveOrUpdate)
-            .onErrorMap(DuplicateKeyException.class, err -> new BusinessException("标签不可重复添加", err))
+            .as(tagRepository::save)
             .thenMany(getDeviceTags(deviceId));
     }
 
@@ -839,4 +833,54 @@ public class DeviceInstanceController implements
     }
 
 
+    //更新设备地理位置
+    @PatchMapping("/{deviceId}/geo")
+    @SaveAction
+    @Operation(summary = "更新设备地理位置信息")
+    public Mono<GeoPoint> patchGeo(@PathVariable @Parameter(description = "设备ID") String deviceId,
+                                   @RequestBody GeoPoint geoPoint) {
+        return instanceService.createUpdate()
+            .where(DeviceInstanceEntity::getId,deviceId)
+            .set(DeviceInstanceEntity::getCoordinate,geoPoint)
+            .execute()
+            .flatMap(ignore->
+                instanceService.findById(deviceId)
+                    .map(DeviceGeoDto::of)
+                    .flatMap(geo-> elasticSearchService.save(GeoIndexProvider.GEO.getIndex(),geo))
+            )
+            .thenReturn(geoPoint);
+    }
+
+
+    //获取设备地理位置
+    @GetMapping("/{deviceId}/geo")
+    @SaveAction
+    @Operation(summary = "获取设备地理位置信息")
+    public Mono<GeoPoint> getGeo(@PathVariable @Parameter(description = "设备ID") String deviceId) {
+        return instanceService.findById(deviceId).map(DeviceInstanceEntity::getCoordinate);
+    }
+
+
+    /**
+     * 分页查询设备信息
+     * @param query
+     * @param shapes
+     * @return
+     */
+    @GetMapping("/geo/_query/{bool}")
+    public Mono<PagerResult<DeviceInstanceEntity>> queryPagergeo(QueryParamEntity query,@PathVariable("bool") boolean s) {
+        if(s){
+//            /**
+//             * 没有查询区域
+//             */
+            query.setIncludes(CollectionUtil.newHashSet("id","name","coordinate","productId","productName"));
+            return instanceService.queryPager(query);
+        }else {
+            /**
+             * 查询区域
+             * es查询
+             */
+             return elasticSearchService.queryPager(GeoIndexProvider.GEO,query,DeviceInstanceEntity.class);
+        }
+    }
 }

+ 14 - 5
jetlinks-manager/device-manager/src/main/java/org/jetlinks/community/device/web/GeoController.java

@@ -2,12 +2,16 @@ package org.jetlinks.community.device.web;
 
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.util.StrUtil;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.AllArgsConstructor;
 import org.hibernate.validator.constraints.Length;
 import org.hswebframework.web.api.crud.entity.PagerResult;
+import org.hswebframework.web.api.crud.entity.QueryParamEntity;
 import org.hswebframework.web.authorization.annotation.Authorize;
 import org.hswebframework.web.authorization.annotation.Resource;
+import org.hswebframework.web.authorization.annotation.SaveAction;
 import org.hswebframework.web.crud.service.ReactiveCrudService;
 import org.hswebframework.web.crud.web.reactive.ReactiveServiceCrudController;
 import org.jetlinks.community.device.entity.DeviceTagEntity;
@@ -15,14 +19,12 @@ import org.jetlinks.community.device.entity.geo.GeoEntity;
 import org.jetlinks.community.device.entity.geo.GeoProperty;
 import org.jetlinks.community.device.entity.geo.Geometry;
 import org.jetlinks.community.device.service.DeviceTagsService;
+import org.jetlinks.community.device.service.LocalDeviceInstanceService;
 import org.jetlinks.community.device.service.LocalGeoPropertyService;
 import org.jetlinks.community.device.web.request.GeoPayload;
 import org.jetlinks.community.device.web.request.GeoRequestParam;
 import org.jetlinks.core.metadata.types.GeoType;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 import reactor.util.function.Tuple2;
@@ -48,7 +50,7 @@ import java.util.stream.Collectors;
 @AllArgsConstructor
 public class GeoController  implements ReactiveServiceCrudController<GeoProperty, String> {
     private final LocalGeoPropertyService geoService;
-    private final DeviceTagsService tagsService;
+    private final LocalDeviceInstanceService instanceService;
 
 
     @PostMapping("/_search/geo.json")
@@ -93,6 +95,13 @@ public class GeoController  implements ReactiveServiceCrudController<GeoProperty
             }).then();
     }
 
+
+
+    @Override
+    public Mono<PagerResult<GeoProperty>> queryPager(QueryParamEntity query) {
+        return null;
+    }
+
     @Override
     public ReactiveCrudService<GeoProperty, String> getService() {
         return geoService;