Commit 3a832d9fb46e2078745f8040aee72134a07dc942
1 parent
28a30d4b
feat(iot):【设备订单:50%】简化设备定位功能,支持 GeoLocation 自动更新,基于 calm-roaming-pillow.md
Showing
14 changed files
with
109 additions
and
89 deletions
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceController.java
| ... | ... | @@ -8,7 +8,6 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 8 | 8 | import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; |
| 9 | 9 | import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*; |
| 10 | 10 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; |
| 11 | -import cn.iocoder.yudao.module.iot.enums.product.IotLocationTypeEnum; | |
| 12 | 11 | import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; |
| 13 | 12 | import io.swagger.v3.oas.annotations.Operation; |
| 14 | 13 | import io.swagger.v3.oas.annotations.Parameter; |
| ... | ... | @@ -153,10 +152,9 @@ public class IotDeviceController { |
| 153 | 152 | // 手动创建导出 demo |
| 154 | 153 | List<IotDeviceImportExcelVO> list = Arrays.asList( |
| 155 | 154 | IotDeviceImportExcelVO.builder().deviceName("温度传感器001").parentDeviceName("gateway110") |
| 156 | - .productKey("1de24640dfe").groupNames("灰度分组,生产分组") | |
| 157 | - .locationType(IotLocationTypeEnum.IP.getType()).build(), | |
| 155 | + .productKey("1de24640dfe").groupNames("灰度分组,生产分组").build(), | |
| 158 | 156 | IotDeviceImportExcelVO.builder().deviceName("biubiu").productKey("YzvHxd4r67sT4s2B") |
| 159 | - .groupNames("").locationType(IotLocationTypeEnum.MANUAL.getType()).build()); | |
| 157 | + .groupNames("").build()); | |
| 160 | 158 | // 输出 |
| 161 | 159 | ExcelUtils.write(response, "设备导入模板.xls", "数据", IotDeviceImportExcelVO.class, list); |
| 162 | 160 | } | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceImportExcelVO.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.controller.admin.device.vo.device; |
| 2 | 2 | |
| 3 | 3 | import cn.idev.excel.annotation.ExcelProperty; |
| 4 | -import cn.iocoder.yudao.framework.common.validation.InEnum; | |
| 5 | -import cn.iocoder.yudao.module.iot.enums.product.IotLocationTypeEnum; | |
| 6 | 4 | import io.swagger.v3.oas.annotations.media.Schema; |
| 7 | 5 | import jakarta.validation.constraints.NotEmpty; |
| 8 | -import jakarta.validation.constraints.NotNull; | |
| 9 | 6 | import lombok.AllArgsConstructor; |
| 10 | 7 | import lombok.Builder; |
| 11 | 8 | import lombok.Data; |
| ... | ... | @@ -35,9 +32,4 @@ public class IotDeviceImportExcelVO { |
| 35 | 32 | @ExcelProperty("设备分组") |
| 36 | 33 | private String groupNames; |
| 37 | 34 | |
| 38 | - @ExcelProperty("上报方式(1:IP 定位, 2:设备上报,3:手动定位)") | |
| 39 | - @NotNull(message = "上报方式不能为空") | |
| 40 | - @InEnum(IotLocationTypeEnum.class) | |
| 41 | - private Integer locationType; | |
| 42 | - | |
| 43 | 35 | } | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceRespVO.java
| ... | ... | @@ -84,11 +84,6 @@ public class IotDeviceRespVO { |
| 84 | 84 | @Schema(description = "设备配置", example = "{\"abc\": \"efg\"}") |
| 85 | 85 | private String config; |
| 86 | 86 | |
| 87 | - @Schema(description = "定位方式", example = "2") | |
| 88 | - @ExcelProperty(value = "定位方式", converter = DictConvert.class) | |
| 89 | - @DictFormat(DictTypeConstants.LOCATION_TYPE) | |
| 90 | - private Integer locationType; | |
| 91 | - | |
| 92 | 87 | @Schema(description = "设备位置的纬度", example = "45.000000") |
| 93 | 88 | private BigDecimal latitude; |
| 94 | 89 | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceSaveReqVO.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.controller.admin.device.vo.device; |
| 2 | 2 | |
| 3 | -import cn.iocoder.yudao.framework.common.validation.InEnum; | |
| 4 | -import cn.iocoder.yudao.module.iot.enums.product.IotLocationTypeEnum; | |
| 5 | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 6 | 4 | import lombok.Data; |
| 7 | 5 | |
| ... | ... | @@ -39,10 +37,6 @@ public class IotDeviceSaveReqVO { |
| 39 | 37 | @Schema(description = "设备配置", example = "{\"abc\": \"efg\"}") |
| 40 | 38 | private String config; |
| 41 | 39 | |
| 42 | - @Schema(description = "定位类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") | |
| 43 | - @InEnum(value = IotLocationTypeEnum.class, message = "定位方式必须是 {value}") | |
| 44 | - private Integer locationType; | |
| 45 | - | |
| 46 | 40 | @Schema(description = "设备位置的纬度", example = "16380") |
| 47 | 41 | private BigDecimal latitude; |
| 48 | 42 | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductController.java
| ... | ... | @@ -147,7 +147,7 @@ public class IotProductController { |
| 147 | 147 | List<IotProductDO> list = productService.getProductList(); |
| 148 | 148 | return success(convertList(list, product -> // 只返回 id、name 字段 |
| 149 | 149 | new IotProductRespVO().setId(product.getId()).setName(product.getName()).setStatus(product.getStatus()) |
| 150 | - .setDeviceType(product.getDeviceType()).setLocationType(product.getLocationType()))); | |
| 150 | + .setDeviceType(product.getDeviceType()))); | |
| 151 | 151 | } |
| 152 | 152 | |
| 153 | 153 | } |
| 154 | 154 | \ No newline at end of file | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductRespVO.java
| ... | ... | @@ -61,11 +61,6 @@ public class IotProductRespVO { |
| 61 | 61 | @DictFormat(DictTypeConstants.NET_TYPE) |
| 62 | 62 | private Integer netType; |
| 63 | 63 | |
| 64 | - @Schema(description = "定位方式", example = "2") | |
| 65 | - @ExcelProperty(value = "定位方式", converter = DictConvert.class) | |
| 66 | - @DictFormat(DictTypeConstants.LOCATION_TYPE) | |
| 67 | - private Integer locationType; | |
| 68 | - | |
| 69 | 64 | @Schema(description = "数据格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") |
| 70 | 65 | @ExcelProperty(value = "数据格式", converter = DictConvert.class) |
| 71 | 66 | @DictFormat(DictTypeConstants.CODEC_TYPE) | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductSaveReqVO.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.controller.admin.product.vo.product; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.validation.InEnum; |
| 4 | -import cn.iocoder.yudao.module.iot.enums.product.IotLocationTypeEnum; | |
| 5 | 4 | import cn.iocoder.yudao.module.iot.enums.product.IotNetTypeEnum; |
| 6 | 5 | import cn.iocoder.yudao.module.iot.enums.product.IotProductDeviceTypeEnum; |
| 7 | 6 | import io.swagger.v3.oas.annotations.media.Schema; |
| ... | ... | @@ -45,10 +44,6 @@ public class IotProductSaveReqVO { |
| 45 | 44 | @InEnum(value = IotNetTypeEnum.class, message = "联网方式必须是 {value}") |
| 46 | 45 | private Integer netType; |
| 47 | 46 | |
| 48 | - @Schema(description = "定位类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") | |
| 49 | - @InEnum(value = IotLocationTypeEnum.class, message = "定位方式必须是 {value}") | |
| 50 | - private Integer locationType; | |
| 51 | - | |
| 52 | 47 | @Schema(description = "数据格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") |
| 53 | 48 | @NotEmpty(message = "数据格式不能为空") |
| 54 | 49 | private String codecType; | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDO.java
| ... | ... | @@ -130,12 +130,6 @@ public class IotDeviceDO extends TenantBaseDO { |
| 130 | 130 | private String authType; |
| 131 | 131 | |
| 132 | 132 | /** |
| 133 | - * 定位方式 | |
| 134 | - * <p> | |
| 135 | - * 枚举 {@link cn.iocoder.yudao.module.iot.enums.product.IotLocationTypeEnum} | |
| 136 | - */ | |
| 137 | - private Integer locationType; | |
| 138 | - /** | |
| 139 | 133 | * 设备位置的纬度 |
| 140 | 134 | */ |
| 141 | 135 | private BigDecimal latitude; | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductDO.java
| ... | ... | @@ -70,12 +70,6 @@ public class IotProductDO extends TenantBaseDO { |
| 70 | 70 | */ |
| 71 | 71 | private Integer netType; |
| 72 | 72 | /** |
| 73 | - * 定位方式 | |
| 74 | - * <p> | |
| 75 | - * 枚举 {@link cn.iocoder.yudao.module.iot.enums.product.IotLocationTypeEnum} | |
| 76 | - */ | |
| 77 | - private Integer locationType; | |
| 78 | - /** | |
| 79 | 73 | * 数据格式(编解码器类型) |
| 80 | 74 | * <p> |
| 81 | 75 | * 字典 {@link cn.iocoder.yudao.module.iot.enums.DictTypeConstants#CODEC_TYPE} | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotLocationTypeEnum.java deleted
| 1 | -package cn.iocoder.yudao.module.iot.enums.product; | |
| 2 | - | |
| 3 | -import cn.iocoder.yudao.framework.common.core.ArrayValuable; | |
| 4 | -import lombok.AllArgsConstructor; | |
| 5 | -import lombok.Getter; | |
| 6 | - | |
| 7 | -import java.util.Arrays; | |
| 8 | - | |
| 9 | -/** | |
| 10 | - * IoT 定位方式枚举类 | |
| 11 | - * | |
| 12 | - * @author alwayssuper | |
| 13 | - */ | |
| 14 | -@AllArgsConstructor | |
| 15 | -@Getter | |
| 16 | -public enum IotLocationTypeEnum implements ArrayValuable<Integer> { | |
| 17 | - | |
| 18 | - IP(1, "IP 定位"), | |
| 19 | - DEVICE(2, "设备上报"), | |
| 20 | - MANUAL(3, "手动定位"); | |
| 21 | - | |
| 22 | - public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotLocationTypeEnum::getType).toArray(Integer[]::new); | |
| 23 | - | |
| 24 | - /** | |
| 25 | - * 类型 | |
| 26 | - */ | |
| 27 | - private final Integer type; | |
| 28 | - /** | |
| 29 | - * 描述 | |
| 30 | - */ | |
| 31 | - private final String description; | |
| 32 | - | |
| 33 | - @Override | |
| 34 | - public Integer[] array() { | |
| 35 | - return ARRAYS; | |
| 36 | - } | |
| 37 | - | |
| 38 | -} |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceService.java
| ... | ... | @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; |
| 8 | 8 | import jakarta.validation.Valid; |
| 9 | 9 | |
| 10 | 10 | import javax.annotation.Nullable; |
| 11 | +import java.math.BigDecimal; | |
| 11 | 12 | import java.time.LocalDateTime; |
| 12 | 13 | import java.util.Collection; |
| 13 | 14 | import java.util.List; |
| ... | ... | @@ -271,4 +272,13 @@ public interface IotDeviceService { |
| 271 | 272 | */ |
| 272 | 273 | void updateDeviceFirmware(Long deviceId, Long firmwareId); |
| 273 | 274 | |
| 275 | + /** | |
| 276 | + * 更新设备定位信息(GeoLocation 上报时调用) | |
| 277 | + * | |
| 278 | + * @param device 设备信息(用于清除缓存) | |
| 279 | + * @param longitude 经度 | |
| 280 | + * @param latitude 纬度 | |
| 281 | + */ | |
| 282 | + void updateDeviceLocation(IotDeviceDO device, BigDecimal longitude, BigDecimal latitude); | |
| 283 | + | |
| 274 | 284 | } | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java
| ... | ... | @@ -34,6 +34,7 @@ import org.springframework.transaction.annotation.Transactional; |
| 34 | 34 | import org.springframework.validation.annotation.Validated; |
| 35 | 35 | |
| 36 | 36 | import javax.annotation.Nullable; |
| 37 | +import java.math.BigDecimal; | |
| 37 | 38 | import java.time.LocalDateTime; |
| 38 | 39 | import java.util.*; |
| 39 | 40 | |
| ... | ... | @@ -376,8 +377,7 @@ public class IotDeviceServiceImpl implements IotDeviceService { |
| 376 | 377 | if (existDevice == null) { |
| 377 | 378 | createDevice(new IotDeviceSaveReqVO() |
| 378 | 379 | .setDeviceName(importDevice.getDeviceName()) |
| 379 | - .setProductId(product.getId()).setGatewayId(gatewayId).setGroupIds(groupIds) | |
| 380 | - .setLocationType(importDevice.getLocationType())); | |
| 380 | + .setProductId(product.getId()).setGatewayId(gatewayId).setGroupIds(groupIds)); | |
| 381 | 381 | respVO.getCreateDeviceNames().add(importDevice.getDeviceName()); |
| 382 | 382 | return; |
| 383 | 383 | } |
| ... | ... | @@ -386,7 +386,7 @@ public class IotDeviceServiceImpl implements IotDeviceService { |
| 386 | 386 | throw exception(DEVICE_KEY_EXISTS); |
| 387 | 387 | } |
| 388 | 388 | updateDevice(new IotDeviceSaveReqVO().setId(existDevice.getId()) |
| 389 | - .setGatewayId(gatewayId).setGroupIds(groupIds).setLocationType(importDevice.getLocationType())); | |
| 389 | + .setGatewayId(gatewayId).setGroupIds(groupIds)); | |
| 390 | 390 | respVO.getUpdateDeviceNames().add(importDevice.getDeviceName()); |
| 391 | 391 | } catch (ServiceException ex) { |
| 392 | 392 | respVO.getFailureDeviceNames().put(importDevice.getDeviceName(), ex.getMessage()); |
| ... | ... | @@ -490,15 +490,25 @@ public class IotDeviceServiceImpl implements IotDeviceService { |
| 490 | 490 | public void updateDeviceFirmware(Long deviceId, Long firmwareId) { |
| 491 | 491 | // 1. 校验设备是否存在 |
| 492 | 492 | IotDeviceDO device = validateDeviceExists(deviceId); |
| 493 | - | |
| 493 | + | |
| 494 | 494 | // 2. 更新设备固件版本 |
| 495 | 495 | IotDeviceDO updateObj = new IotDeviceDO().setId(deviceId).setFirmwareId(firmwareId); |
| 496 | 496 | deviceMapper.updateById(updateObj); |
| 497 | - | |
| 497 | + | |
| 498 | 498 | // 3. 清空对应缓存 |
| 499 | 499 | deleteDeviceCache(device); |
| 500 | 500 | } |
| 501 | 501 | |
| 502 | + @Override | |
| 503 | + public void updateDeviceLocation(IotDeviceDO device, BigDecimal longitude, BigDecimal latitude) { | |
| 504 | + // 1. 更新定位信息 | |
| 505 | + deviceMapper.updateById(new IotDeviceDO().setId(device.getId()) | |
| 506 | + .setLongitude(longitude).setLatitude(latitude)); | |
| 507 | + | |
| 508 | + // 2. 清空对应缓存 | |
| 509 | + deleteDeviceCache(device); | |
| 510 | + } | |
| 511 | + | |
| 502 | 512 | private IotDeviceServiceImpl getSelf() { |
| 503 | 513 | return SpringUtil.getBean(getClass()); |
| 504 | 514 | } | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/property/IotDevicePropertyServiceImpl.java
| ... | ... | @@ -22,6 +22,7 @@ import cn.iocoder.yudao.module.iot.dal.tdengine.IotDevicePropertyMapper; |
| 22 | 22 | import cn.iocoder.yudao.module.iot.enums.thingmodel.IotDataSpecsDataTypeEnum; |
| 23 | 23 | import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum; |
| 24 | 24 | import cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField; |
| 25 | +import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; | |
| 25 | 26 | import cn.iocoder.yudao.module.iot.service.product.IotProductService; |
| 26 | 27 | import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService; |
| 27 | 28 | import jakarta.annotation.Resource; |
| ... | ... | @@ -30,6 +31,7 @@ import org.springframework.context.annotation.Lazy; |
| 30 | 31 | import org.springframework.scheduling.annotation.Async; |
| 31 | 32 | import org.springframework.stereotype.Service; |
| 32 | 33 | |
| 34 | +import java.math.BigDecimal; | |
| 33 | 35 | import java.time.LocalDateTime; |
| 34 | 36 | import java.util.*; |
| 35 | 37 | |
| ... | ... | @@ -66,6 +68,9 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService { |
| 66 | 68 | @Resource |
| 67 | 69 | @Lazy // 延迟加载,解决循环依赖 |
| 68 | 70 | private IotProductService productService; |
| 71 | + @Resource | |
| 72 | + @Lazy // 延迟加载,解决循环依赖 | |
| 73 | + private IotDeviceService deviceService; | |
| 69 | 74 | |
| 70 | 75 | @Resource |
| 71 | 76 | private DevicePropertyRedisDAO deviceDataRedisDAO; |
| ... | ... | @@ -168,6 +173,9 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService { |
| 168 | 173 | Map<String, IotDevicePropertyDO> properties2 = convertMap(properties.entrySet(), Map.Entry::getKey, entry -> |
| 169 | 174 | IotDevicePropertyDO.builder().value(entry.getValue()).updateTime(message.getReportTime()).build()); |
| 170 | 175 | deviceDataRedisDAO.putAll(device.getId(), properties2); |
| 176 | + | |
| 177 | + // 2.3 提取 GeoLocation 并更新设备定位 | |
| 178 | + extractAndUpdateDeviceLocation(device, (Map<?, ?>) message.getParams()); | |
| 171 | 179 | } |
| 172 | 180 | |
| 173 | 181 | @Override |
| ... | ... | @@ -213,4 +221,73 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService { |
| 213 | 221 | return deviceServerIdRedisDAO.get(id); |
| 214 | 222 | } |
| 215 | 223 | |
| 224 | + // ========== 设备定位相关操作 ========== | |
| 225 | + | |
| 226 | + /** | |
| 227 | + * 从属性中提取 GeoLocation 并更新设备定位 | |
| 228 | + * | |
| 229 | + * @see <a href="https://help.aliyun.com/zh/iot/user-guide/device-geolocation">阿里云规范</a> | |
| 230 | + * GeoLocation 结构体包含:Longitude, Latitude, Altitude, CoordinateSystem | |
| 231 | + */ | |
| 232 | + private void extractAndUpdateDeviceLocation(IotDeviceDO device, Map<?, ?> params) { | |
| 233 | + // 1. 解析 GeoLocation 经纬度坐标 | |
| 234 | + Double[] location = parseGeoLocation(params); | |
| 235 | + if (location == null) { | |
| 236 | + return; | |
| 237 | + } | |
| 238 | + | |
| 239 | + // 2. 更新设备定位 | |
| 240 | + deviceService.updateDeviceLocation(device, | |
| 241 | + BigDecimal.valueOf(location[0]), BigDecimal.valueOf(location[1])); | |
| 242 | + log.info("[extractAndUpdateGeoLocation][设备({}) 定位更新: lng={}, lat={}]", | |
| 243 | + device.getId(), location[0], location[1]); | |
| 244 | + } | |
| 245 | + | |
| 246 | + /** | |
| 247 | + * 从属性参数中解析 GeoLocation,返回经纬度坐标数组 [longitude, latitude] | |
| 248 | + * | |
| 249 | + * @param params 属性参数 | |
| 250 | + * @return [经度, 纬度],解析失败返回 null | |
| 251 | + */ | |
| 252 | + @SuppressWarnings("unchecked") | |
| 253 | + // TODO @AI:返回 BigDecimal 数组; | |
| 254 | + private Double[] parseGeoLocation(Map<?, ?> params) { | |
| 255 | + if (params == null) { | |
| 256 | + return null; | |
| 257 | + } | |
| 258 | + // 1. 查找 GeoLocation 属性(标识符为 GeoLocation 或 geoLocation) | |
| 259 | + Object geoValue = params.get("GeoLocation"); | |
| 260 | + if (geoValue == null) { | |
| 261 | + geoValue = params.get("geoLocation"); | |
| 262 | + } | |
| 263 | + if (geoValue == null) { | |
| 264 | + return null; | |
| 265 | + } | |
| 266 | + | |
| 267 | + // 2. 转换为 Map | |
| 268 | + Map<String, Object> geoLocation = null; | |
| 269 | + if (geoValue instanceof Map) { | |
| 270 | + geoLocation = (Map<String, Object>) geoValue; | |
| 271 | + } else if (geoValue instanceof String) { | |
| 272 | + geoLocation = JsonUtils.parseObject((String) geoValue, Map.class); | |
| 273 | + } | |
| 274 | + if (geoLocation == null) { | |
| 275 | + return null; | |
| 276 | + } | |
| 277 | + | |
| 278 | + // 3. 提取经纬度(支持阿里云命名规范:首字母大写) | |
| 279 | + Double longitude = MapUtil.getDouble(geoLocation, "Longitude"); | |
| 280 | + if (longitude == null) { | |
| 281 | + longitude = MapUtil.getDouble(geoLocation, "longitude"); | |
| 282 | + } | |
| 283 | + Double latitude = MapUtil.getDouble(geoLocation, "Latitude"); | |
| 284 | + if (latitude == null) { | |
| 285 | + latitude = MapUtil.getDouble(geoLocation, "latitude"); | |
| 286 | + } | |
| 287 | + if (longitude == null || latitude == null) { | |
| 288 | + return null; | |
| 289 | + } | |
| 290 | + return new Double[]{longitude, latitude}; | |
| 291 | + } | |
| 292 | + | |
| 216 | 293 | } |
| 217 | 294 | \ No newline at end of file | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataRuleServiceImpl.java
| ... | ... | @@ -271,6 +271,10 @@ public class IotDataRuleServiceImpl implements IotDataRuleService { |
| 271 | 271 | if (ObjUtil.notEqual(action.getType(), dataSink.getType())) { |
| 272 | 272 | return; |
| 273 | 273 | } |
| 274 | + if (CommonStatusEnum.isDisable(dataSink.getStatus())) { | |
| 275 | + log.warn("[executeDataRuleAction][消息({}) 数据目的({}) 状态为禁用]", message.getId(), dataSink.getId()); | |
| 276 | + return; | |
| 277 | + } | |
| 274 | 278 | try { |
| 275 | 279 | action.execute(message, dataSink); |
| 276 | 280 | log.info("[executeDataRuleAction][消息({}) 数据目的({}) 执行成功]", message.getId(), dataSink.getId()); | ... | ... |