Commit baa779a271ec94017060c0f1da033c87e64d1343

Authored by YunaiV
1 parent b800d274

feat(iot): 新增产品 TDengine 表结构同步接口

yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductController.http 0 → 100644
  1 +### 请求 /iot/product/sync-property-table 接口 => 成功
  2 +POST {{baseUrl}}/iot/product/sync-property-table
  3 +Content-Type: application/json
  4 +tenant-id: {{adminTenantId}}
  5 +Authorization: Bearer {{token}}
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 { @@ -141,6 +141,14 @@ public class IotProductController {
141 result.getData().getList()); 141 result.getData().getList());
142 } 142 }
143 143
  144 + @PostMapping("/sync-property-table")
  145 + @Operation(summary = "同步产品属性表结构到 TDengine")
  146 + @PreAuthorize("@ss.hasPermission('iot:product:update')")
  147 + public CommonResult<Boolean> syncProductPropertyTable() {
  148 + productService.syncProductPropertyTable();
  149 + return success(true);
  150 + }
  151 +
144 @GetMapping("/simple-list") 152 @GetMapping("/simple-list")
145 @Operation(summary = "获取产品的精简信息列表", description = "主要用于前端的下拉选项") 153 @Operation(summary = "获取产品的精简信息列表", description = "主要用于前端的下拉选项")
146 @Parameter(name = "deviceType", description = "设备类型", example = "1") 154 @Parameter(name = "deviceType", description = "设备类型", example = "1")
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&lt;IotProductDO&gt; { @@ -38,6 +38,10 @@ public interface IotProductMapper extends BaseMapperX&lt;IotProductDO&gt; {
38 .apply("LOWER(product_key) = {0}", productKey.toLowerCase())); 38 .apply("LOWER(product_key) = {0}", productKey.toLowerCase()));
39 } 39 }
40 40
  41 + default List<IotProductDO> selectListByStatus(Integer status) {
  42 + return selectList(IotProductDO::getStatus, status);
  43 + }
  44 +
41 default Long selectCountByCreateTime(@Nullable LocalDateTime createTime) { 45 default Long selectCountByCreateTime(@Nullable LocalDateTime createTime) {
42 return selectCount(new LambdaQueryWrapperX<IotProductDO>() 46 return selectCount(new LambdaQueryWrapperX<IotProductDO>()
43 .geIfPresent(IotProductDO::getCreateTime, createTime)); 47 .geIfPresent(IotProductDO::getCreateTime, createTime));
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 { @@ -149,4 +149,11 @@ public interface IotProductService {
149 */ 149 */
150 void validateProductsExist(Collection<Long> ids); 150 void validateProductsExist(Collection<Long> ids);
151 151
  152 + /**
  153 + * 同步产品的 TDengine 表结构
  154 + *
  155 + * 目的:当 MySQL 和 TDengine 不同步时,强制将已发布产品的表结构同步到 TDengine 中
  156 + */
  157 + void syncProductPropertyTable();
  158 +
152 } 159 }
153 \ No newline at end of file 160 \ No newline at end of file
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; @@ -15,6 +15,7 @@ import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
15 import cn.iocoder.yudao.module.iot.service.device.property.IotDevicePropertyService; 15 import cn.iocoder.yudao.module.iot.service.device.property.IotDevicePropertyService;
16 import com.baomidou.dynamic.datasource.annotation.DSTransactional; 16 import com.baomidou.dynamic.datasource.annotation.DSTransactional;
17 import jakarta.annotation.Resource; 17 import jakarta.annotation.Resource;
  18 +import lombok.extern.slf4j.Slf4j;
18 import org.springframework.cache.annotation.CacheEvict; 19 import org.springframework.cache.annotation.CacheEvict;
19 import org.springframework.cache.annotation.Cacheable; 20 import org.springframework.cache.annotation.Cacheable;
20 import org.springframework.context.annotation.Lazy; 21 import org.springframework.context.annotation.Lazy;
@@ -34,6 +35,7 @@ import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*; @@ -34,6 +35,7 @@ import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
34 * 35 *
35 * @author ahh 36 * @author ahh
36 */ 37 */
  38 +@Slf4j
37 @Service 39 @Service
38 @Validated 40 @Validated
39 public class IotProductServiceImpl implements IotProductService { 41 public class IotProductServiceImpl implements IotProductService {
@@ -179,6 +181,27 @@ public class IotProductServiceImpl implements IotProductService { @@ -179,6 +181,27 @@ public class IotProductServiceImpl implements IotProductService {
179 } 181 }
180 182
181 @Override 183 @Override
  184 + public void syncProductPropertyTable() {
  185 + // 1. 获取所有已发布的产品
  186 + List<IotProductDO> products = productMapper.selectListByStatus(
  187 + IotProductStatusEnum.PUBLISHED.getStatus());
  188 + log.info("[syncProductPropertyTable][开始同步,已发布产品数量({})]", products.size());
  189 +
  190 + // 2. 遍历同步 TDengine 表结构(创建产品超级表数据模型)
  191 + int successCount = 0;
  192 + for (IotProductDO product : products) {
  193 + try {
  194 + devicePropertyDataService.defineDevicePropertyData(product.getId());
  195 + successCount++;
  196 + log.info("[syncProductPropertyTable][产品({}/{}) 同步成功]", product.getId(), product.getName());
  197 + } catch (Exception e) {
  198 + log.error("[syncProductPropertyTable][产品({}/{}) 同步失败]", product.getId(), product.getName(), e);
  199 + }
  200 + }
  201 + log.info("[syncProductPropertyTable][同步完成,成功({}/{})个]", successCount, products.size());
  202 + }
  203 +
  204 + @Override
182 public void validateProductsExist(Collection<Long> ids) { 205 public void validateProductsExist(Collection<Long> ids) {
183 if (CollUtil.isEmpty(ids)) { 206 if (CollUtil.isEmpty(ids)) {
184 return; 207 return;
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; @@ -7,7 +7,7 @@ import lombok.RequiredArgsConstructor;
7 import java.util.Arrays; 7 import java.util.Arrays;
8 8
9 /** 9 /**
10 - * IoT Modbus 模式枚举 10 + * IoT Modbus 工作模式枚举
11 * 11 *
12 * @author 芋道源码 12 * @author 芋道源码
13 */ 13 */
@@ -16,18 +16,18 @@ import java.util.Arrays; @@ -16,18 +16,18 @@ import java.util.Arrays;
16 public enum IotModbusModeEnum implements ArrayValuable<Integer> { 16 public enum IotModbusModeEnum implements ArrayValuable<Integer> {
17 17
18 POLLING(1, "云端轮询"), 18 POLLING(1, "云端轮询"),
19 - ACTIVE_REPORT(2, "主动上报"); 19 + ACTIVE_REPORT(2, "边缘采集");
20 20
21 public static final Integer[] ARRAYS = Arrays.stream(values()) 21 public static final Integer[] ARRAYS = Arrays.stream(values())
22 .map(IotModbusModeEnum::getMode) 22 .map(IotModbusModeEnum::getMode)
23 .toArray(Integer[]::new); 23 .toArray(Integer[]::new);
24 24
25 /** 25 /**
26 - * 模式 26 + * 工作模式
27 */ 27 */
28 private final Integer mode; 28 private final Integer mode;
29 /** 29 /**
30 - * 名称 30 + * 模式名称
31 */ 31 */
32 private final String name; 32 private final String name;
33 33