diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductController.http b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductController.http new file mode 100644 index 0000000000..e4e258985f --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductController.http @@ -0,0 +1,5 @@ +### 请求 /iot/product/sync-property-table 接口 => 成功 +POST {{baseUrl}}/iot/product/sync-property-table +Content-Type: application/json +tenant-id: {{adminTenantId}} +Authorization: Bearer {{token}} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductController.java index 043f48772b..130c45d6a7 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductController.java @@ -141,6 +141,14 @@ public class IotProductController { result.getData().getList()); } + @PostMapping("/sync-property-table") + @Operation(summary = "同步产品属性表结构到 TDengine") + @PreAuthorize("@ss.hasPermission('iot:product:update')") + public CommonResult syncProductPropertyTable() { + productService.syncProductPropertyTable(); + return success(true); + } + @GetMapping("/simple-list") @Operation(summary = "获取产品的精简信息列表", description = "主要用于前端的下拉选项") @Parameter(name = "deviceType", description = "设备类型", example = "1") diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java index 2ed27dbb67..8c611d0d46 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java @@ -38,6 +38,10 @@ public interface IotProductMapper extends BaseMapperX { .apply("LOWER(product_key) = {0}", productKey.toLowerCase())); } + default List selectListByStatus(Integer status) { + return selectList(IotProductDO::getStatus, status); + } + default Long selectCountByCreateTime(@Nullable LocalDateTime createTime) { return selectCount(new LambdaQueryWrapperX() .geIfPresent(IotProductDO::getCreateTime, createTime)); diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductService.java index 3d68fb59e1..f31961cfd1 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductService.java @@ -149,4 +149,11 @@ public interface IotProductService { */ void validateProductsExist(Collection ids); + /** + * 同步产品的 TDengine 表结构 + * + * 目的:当 MySQL 和 TDengine 不同步时,强制将已发布产品的表结构同步到 TDengine 中 + */ + void syncProductPropertyTable(); + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java index 49d7f36958..4c8a789b93 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java @@ -15,6 +15,7 @@ import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; import cn.iocoder.yudao.module.iot.service.device.property.IotDevicePropertyService; import com.baomidou.dynamic.datasource.annotation.DSTransactional; import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.context.annotation.Lazy; @@ -34,6 +35,7 @@ import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*; * * @author ahh */ +@Slf4j @Service @Validated public class IotProductServiceImpl implements IotProductService { @@ -178,6 +180,27 @@ public class IotProductServiceImpl implements IotProductService { return productMapper.selectByIds(ids); } + @Override + public void syncProductPropertyTable() { + // 1. 获取所有已发布的产品 + List products = productMapper.selectListByStatus( + IotProductStatusEnum.PUBLISHED.getStatus()); + log.info("[syncProductPropertyTable][开始同步,已发布产品数量({})]", products.size()); + + // 2. 遍历同步 TDengine 表结构(创建产品超级表数据模型) + int successCount = 0; + for (IotProductDO product : products) { + try { + devicePropertyDataService.defineDevicePropertyData(product.getId()); + successCount++; + log.info("[syncProductPropertyTable][产品({}/{}) 同步成功]", product.getId(), product.getName()); + } catch (Exception e) { + log.error("[syncProductPropertyTable][产品({}/{}) 同步失败]", product.getId(), product.getName(), e); + } + } + log.info("[syncProductPropertyTable][同步完成,成功({}/{})个]", successCount, products.size()); + } + @Override public void validateProductsExist(Collection ids) { if (CollUtil.isEmpty(ids)) { diff --git a/yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/enums/IotModbusModeEnum.java b/yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/enums/IotModbusModeEnum.java index e8bcf2e68c..3736745918 100644 --- a/yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/enums/IotModbusModeEnum.java +++ b/yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/enums/IotModbusModeEnum.java @@ -7,7 +7,7 @@ import lombok.RequiredArgsConstructor; import java.util.Arrays; /** - * IoT Modbus 模式枚举 + * IoT Modbus 工作模式枚举 * * @author 芋道源码 */ @@ -16,18 +16,18 @@ import java.util.Arrays; public enum IotModbusModeEnum implements ArrayValuable { POLLING(1, "云端轮询"), - ACTIVE_REPORT(2, "主动上报"); + ACTIVE_REPORT(2, "边缘采集"); public static final Integer[] ARRAYS = Arrays.stream(values()) .map(IotModbusModeEnum::getMode) .toArray(Integer[]::new); /** - * 模式 + * 工作模式 */ private final Integer mode; /** - * 名称 + * 模式名称 */ private final String name;