Commit f4e9a586e3a0805d8d2834ae027908033ec5f99a

Authored by puhui999
1 parent 94cfc4a1

【功能完善】IOT: ThingModel 服务和事件

yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/ThingModelInputOutputParam.java
... ... @@ -34,6 +34,8 @@ public class ThingModelInputOutputParam {
34 34 private String direction;
35 35 /**
36 36 * 参数的序号。从 0 开始排序,且不能重复。
  37 + *
  38 + * TODO 考虑要不要序号,感觉是要的, 先留一手看看
37 39 */
38 40 private Integer paraOrder;
39 41 /**
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotProductThingModelService.java
... ... @@ -24,6 +24,13 @@ public interface IotProductThingModelService {
24 24 Long createProductThingModel(@Valid IotProductThingModelSaveReqVO createReqVO);
25 25  
26 26 /**
  27 + * 创建超级表数据模型
  28 + *
  29 + * @param productId 产品编号
  30 + */
  31 + void createSuperTableDataModel(Long productId);
  32 +
  33 + /**
27 34 * 更新产品物模型
28 35 *
29 36 * @param updateReqVO 更新信息
... ... @@ -62,13 +69,6 @@ public interface IotProductThingModelService {
62 69 PageResult<IotProductThingModelDO> getProductThingModelPage(IotProductThingModelPageReqVO pageReqVO);
63 70  
64 71 /**
65   - * 创建超级表数据模型
66   - *
67   - * @param productId 产品编号
68   - */
69   - void createSuperTableDataModel(Long productId);
70   -
71   - /**
72 72 * 获得产品物模型列表
73 73 *
74 74 * @param productKey 产品 Key
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotProductThingModelServiceImpl.java
... ... @@ -3,14 +3,10 @@ package cn.iocoder.yudao.module.iot.service.thingmodel;
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.util.ObjectUtil;
5 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6   -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
7   -import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
  6 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
8 7 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelEvent;
9   -import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelProperty;
  8 +import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelInputOutputParam;
10 9 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelService;
11   -import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType.ThingModelArgument;
12   -import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType.ThingModelArrayDataSpecs;
13   -import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType.ThingModelDateOrTextDataSpecs;
14 10 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotProductThingModelPageReqVO;
15 11 import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotProductThingModelSaveReqVO;
16 12 import cn.iocoder.yudao.module.iot.convert.thingmodel.IotProductThingModelConvert;
... ... @@ -18,8 +14,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
18 14 import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotProductThingModelDO;
19 15 import cn.iocoder.yudao.module.iot.dal.mysql.thingmodel.IotProductThingModelMapper;
20 16 import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum;
21   -import cn.iocoder.yudao.module.iot.enums.thingmodel.IotProductThingModelAccessModeEnum;
22   -import cn.iocoder.yudao.module.iot.enums.thingmodel.IotProductThingModelTypeEnum;
  17 +import cn.iocoder.yudao.module.iot.enums.thingmodel.*;
23 18 import cn.iocoder.yudao.module.iot.service.product.IotProductService;
24 19 import cn.iocoder.yudao.module.iot.service.tdengine.IotSuperTableService;
25 20 import jakarta.annotation.Resource;
... ... @@ -31,8 +26,7 @@ import org.springframework.validation.annotation.Validated;
31 26 import java.util.*;
32 27  
33 28 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
34   -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList;
35   -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
  29 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
36 30 import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
37 31  
38 32 /**
... ... @@ -51,7 +45,7 @@ public class IotProductThingModelServiceImpl implements IotProductThingModelServ
51 45 @Resource
52 46 private IotProductService productService;
53 47 @Resource
54   - private IotSuperTableService dbStructureDataService;
  48 + private IotSuperTableService superTableService;
55 49  
56 50 @Override
57 51 @Transactional(rollbackFor = Exception.class)
... ... @@ -79,32 +73,16 @@ public class IotProductThingModelServiceImpl implements IotProductThingModelServ
79 73 return thingModel.getId();
80 74 }
81 75  
82   - private void validateProductStatus(Long createReqVO) {
83   - IotProductDO product = productService.getProduct(createReqVO);
84   - if (Objects.equals(product.getStatus(), IotProductStatusEnum.PUBLISHED.getStatus())) {
85   - throw exception(PRODUCT_STATUS_NOT_ALLOW_THING_MODEL);
86   - }
87   - }
88   -
89   - private void validateNotDefaultEventAndService(String identifier) {
90   - // set, get, post, property, event, time, value 是系统保留字段,不能用于标识符定义
91   - if (CollUtil.containsAny(Arrays.asList("set", "get", "post", "property", "event", "time", "value"), Collections.singletonList(identifier))) {
92   - throw exception(THING_MODEL_IDENTIFIER_INVALID);
93   - }
94   - }
  76 + @Override
  77 + public void createSuperTableDataModel(Long productId) {
  78 + // 1. 查询产品
  79 + IotProductDO product = productService.getProduct(productId);
95 80  
96   - private void validateNameUnique(Long productId, String name) {
97   - IotProductThingModelDO thingModel = productThingModelMapper.selectByProductIdAndName(productId, name);
98   - if (thingModel != null) {
99   - throw exception(THING_MODEL_NAME_EXISTS);
100   - }
101   - }
  81 + // 2. 查询产品的物模型功能列表
  82 + List<IotProductThingModelDO> thingModelList = productThingModelMapper.selectListByProductId(productId);
102 83  
103   - private void validateIdentifierUnique(Long productId, String identifier) {
104   - IotProductThingModelDO thingModel = productThingModelMapper.selectByProductIdAndIdentifier(productId, identifier);
105   - if (thingModel != null) {
106   - throw exception(THING_MODEL_IDENTIFIER_EXISTS);
107   - }
  84 + // 3. 生成 TDengine 的数据模型
  85 + superTableService.createSuperTableDataModel(product, thingModelList);
108 86 }
109 87  
110 88 @Override
... ... @@ -129,13 +107,6 @@ public class IotProductThingModelServiceImpl implements IotProductThingModelServ
129 107 }
130 108 }
131 109  
132   - private void validateIdentifierUniqueForUpdate(Long id, Long productId, String identifier) {
133   - IotProductThingModelDO thingModel = productThingModelMapper.selectByProductIdAndIdentifier(productId, identifier);
134   - if (thingModel != null && ObjectUtil.notEqual(thingModel.getId(), id)) {
135   - throw exception(THING_MODEL_IDENTIFIER_EXISTS);
136   - }
137   - }
138   -
139 110 @Override
140 111 @Transactional(rollbackFor = Exception.class)
141 112 public void deleteProductThingModel(Long id) {
... ... @@ -157,17 +128,6 @@ public class IotProductThingModelServiceImpl implements IotProductThingModelServ
157 128 }
158 129 }
159 130  
160   - /**
161   - * 校验功能是否存在
162   - *
163   - * @param id 功能编号
164   - */
165   - private void validateProductThingModelMapperExists(Long id) {
166   - if (productThingModelMapper.selectById(id) == null) {
167   - throw exception(THING_MODEL_NOT_EXISTS);
168   - }
169   - }
170   -
171 131 @Override
172 132 public IotProductThingModelDO getProductThingModel(Long id) {
173 133 return productThingModelMapper.selectById(id);
... ... @@ -184,20 +144,54 @@ public class IotProductThingModelServiceImpl implements IotProductThingModelServ
184 144 }
185 145  
186 146 @Override
187   - public void createSuperTableDataModel(Long productId) {
188   - // 1. 查询产品
189   - IotProductDO product = productService.getProduct(productId);
  147 + public List<IotProductThingModelDO> getProductThingModelListByProductKey(String productKey) {
  148 + return productThingModelMapper.selectListByProductKey(productKey);
  149 + }
190 150  
191   - // 2. 查询产品的物模型功能列表
192   - List<IotProductThingModelDO> thingModelList = productThingModelMapper.selectListByProductId(productId);
  151 + /**
  152 + * 校验功能是否存在
  153 + *
  154 + * @param id 功能编号
  155 + */
  156 + private void validateProductThingModelMapperExists(Long id) {
  157 + if (productThingModelMapper.selectById(id) == null) {
  158 + throw exception(THING_MODEL_NOT_EXISTS);
  159 + }
  160 + }
193 161  
194   - // 3. 生成 TDengine 的数据模型
195   - dbStructureDataService.createSuperTableDataModel(product, thingModelList);
  162 + private void validateIdentifierUniqueForUpdate(Long id, Long productId, String identifier) {
  163 + IotProductThingModelDO thingModel = productThingModelMapper.selectByProductIdAndIdentifier(productId, identifier);
  164 + if (thingModel != null && ObjectUtil.notEqual(thingModel.getId(), id)) {
  165 + throw exception(THING_MODEL_IDENTIFIER_EXISTS);
  166 + }
196 167 }
197 168  
198   - @Override
199   - public List<IotProductThingModelDO> getProductThingModelListByProductKey(String productKey) {
200   - return productThingModelMapper.selectListByProductKey(productKey);
  169 + private void validateProductStatus(Long createReqVO) {
  170 + IotProductDO product = productService.getProduct(createReqVO);
  171 + if (Objects.equals(product.getStatus(), IotProductStatusEnum.PUBLISHED.getStatus())) {
  172 + throw exception(PRODUCT_STATUS_NOT_ALLOW_THING_MODEL);
  173 + }
  174 + }
  175 +
  176 + private void validateNotDefaultEventAndService(String identifier) {
  177 + // set, get, post, property, event, time, value 是系统保留字段,不能用于标识符定义
  178 + if (CollUtil.containsAny(Arrays.asList("set", "get", "post", "property", "event", "time", "value"), Collections.singletonList(identifier))) {
  179 + throw exception(THING_MODEL_IDENTIFIER_INVALID);
  180 + }
  181 + }
  182 +
  183 + private void validateNameUnique(Long productId, String name) {
  184 + IotProductThingModelDO thingModel = productThingModelMapper.selectByProductIdAndName(productId, name);
  185 + if (thingModel != null) {
  186 + throw exception(THING_MODEL_NAME_EXISTS);
  187 + }
  188 + }
  189 +
  190 + private void validateIdentifierUnique(Long productId, String identifier) {
  191 + IotProductThingModelDO thingModel = productThingModelMapper.selectByProductIdAndIdentifier(productId, identifier);
  192 + if (thingModel != null) {
  193 + throw exception(THING_MODEL_IDENTIFIER_EXISTS);
  194 + }
201 195 }
202 196  
203 197 /**
... ... @@ -210,231 +204,138 @@ public class IotProductThingModelServiceImpl implements IotProductThingModelServ
210 204  
211 205 // 2. 生成新的事件和服务列表
212 206 List<IotProductThingModelDO> newThingModelList = new ArrayList<>();
213   - // 生成属性上报事件
  207 + // 2.1 生成属性上报事件
214 208 ThingModelEvent propertyPostEvent = generatePropertyPostEvent(propertyList);
215 209 if (propertyPostEvent != null) {
216   - IotProductThingModelDO eventThingModel = buildEventThingModelDO(productId, productKey, propertyPostEvent);
217   - newThingModelList.add(eventThingModel);
  210 + newThingModelList.add(buildEventThingModelDO(productId, productKey, propertyPostEvent));
218 211 }
219   - // 生成属性设置服务
  212 + // 2.2 生成属性设置服务
220 213 ThingModelService propertySetService = generatePropertySetService(propertyList);
221 214 if (propertySetService != null) {
222   - IotProductThingModelDO setServiceThingModel = buildServiceThingModelDO(productId, productKey, propertySetService);
223   - newThingModelList.add(setServiceThingModel);
  215 + newThingModelList.add(buildServiceThingModelDO(productId, productKey, propertySetService));
224 216 }
225   - // 生成属性获取服务
  217 + // 2.3 生成属性获取服务
226 218 ThingModelService propertyGetService = generatePropertyGetService(propertyList);
227 219 if (propertyGetService != null) {
228   - IotProductThingModelDO getServiceThingModel = buildServiceThingModelDO(productId, productKey, propertyGetService);
229   - newThingModelList.add(getServiceThingModel);
  220 + newThingModelList.add(buildServiceThingModelDO(productId, productKey, propertyGetService));
230 221 }
231 222  
232   - // 3. 获取数据库中的默认的旧事件和服务列表
  223 + // 3.1 获取数据库中的默认的旧事件和服务列表
233 224 List<IotProductThingModelDO> oldThingModelList = productThingModelMapper.selectListByProductIdAndIdentifiersAndTypes(
234 225 productId,
235 226 Arrays.asList("post", "set", "get"),
236 227 Arrays.asList(IotProductThingModelTypeEnum.EVENT.getType(), IotProductThingModelTypeEnum.SERVICE.getType())
237 228 );
  229 + // 3.2 创建默认的事件和服务
  230 + createDefaultEventsAndServices(oldThingModelList, newThingModelList);
  231 + }
238 232  
239   - // 3.1 使用 diffList 方法比较新旧列表
  233 + /**
  234 + * 创建默认的事件和服务
  235 + */
  236 + private void createDefaultEventsAndServices(List<IotProductThingModelDO> oldThingModelList, List<IotProductThingModelDO> newThingModelList) {
  237 + // 1.1 使用 diffList 方法比较新旧列表
240 238 List<List<IotProductThingModelDO>> diffResult = diffList(oldThingModelList, newThingModelList,
241   - // 继续使用 identifier 和 type 进行比较:这样可以准确地匹配对应的功能对象。
242   - (oldFunc, newFunc) -> Objects.equals(oldFunc.getIdentifier(), newFunc.getIdentifier())
243   - && Objects.equals(oldFunc.getType(), newFunc.getType()));
244   - List<IotProductThingModelDO> createList = diffResult.get(0); // 需要新增的
245   - List<IotProductThingModelDO> updateList = diffResult.get(1); // 需要更新的
246   - List<IotProductThingModelDO> deleteList = diffResult.get(2); // 需要删除的
247   -
248   - // 3.2 批量执行数据库操作
249   - // 新增数据库中的新事件和服务列表
250   - if (CollUtil.isNotEmpty(createList)) {
251   - productThingModelMapper.insertBatch(createList);
  239 + (oldVal, newVal) -> {
  240 + // 继续使用 identifier 和 type 进行比较:这样可以准确地匹配对应的功能对象。
  241 + boolean same = Objects.equals(oldVal.getIdentifier(), newVal.getIdentifier())
  242 + && Objects.equals(oldVal.getType(), newVal.getType());
  243 + if (same) {
  244 + newVal.setId(oldVal.getId()); // 设置编号
  245 + }
  246 + return same;
  247 + });
  248 + // 1.2 批量添加、修改、删除
  249 + if (CollUtil.isNotEmpty(diffResult.get(0))) {
  250 + productThingModelMapper.insertBatch(diffResult.get(0));
252 251 }
253   - // 更新数据库中的事件和服务列表
254   - if (CollUtil.isNotEmpty(updateList)) {
255   - // 首先,为每个需要更新的对象设置其对应的 ID
256   - updateList.forEach(updateFunc -> {
257   - IotProductThingModelDO oldFunc = findThingModelByIdentifierAndType(
258   - oldThingModelList, updateFunc.getIdentifier(), updateFunc.getType());
259   - if (oldFunc != null) {
260   - updateFunc.setId(oldFunc.getId());
261   - }
262   - });
263   - // 过滤掉没有设置 ID 的对象
264   - List<IotProductThingModelDO> validUpdateList = filterList(updateList, thingModel -> thingModel.getId() != null);
265   - // 执行批量更新
266   - if (CollUtil.isNotEmpty(validUpdateList)) {
267   - productThingModelMapper.updateBatch(validUpdateList);
268   - }
  252 + if (CollUtil.isNotEmpty(diffResult.get(1))) {
  253 + productThingModelMapper.updateBatch(diffResult.get(1));
269 254 }
270   -
271   - // 删除数据库中的旧事件和服务列表
272   - if (CollUtil.isNotEmpty(deleteList)) {
273   - Set<Long> idsToDelete = CollectionUtils.convertSet(deleteList, IotProductThingModelDO::getId);
274   - productThingModelMapper.deleteByIds(idsToDelete);
  255 + if (CollUtil.isNotEmpty(diffResult.get(2))) {
  256 + productThingModelMapper.deleteByIds(convertSet(diffResult.get(2), IotProductThingModelDO::getId));
275 257 }
276 258 }
277 259  
278 260 /**
279   - * 根据标识符和类型查找功能对象
280   - */
281   - private IotProductThingModelDO findThingModelByIdentifierAndType(List<IotProductThingModelDO> thingModelList,
282   - String identifier, Integer type) {
283   - return CollUtil.findOne(thingModelList, func ->
284   - Objects.equals(func.getIdentifier(), identifier) && Objects.equals(func.getType(), type));
285   - }
286   -
287   - /**
288 261 * 构建事件功能对象
289 262 */
290 263 private IotProductThingModelDO buildEventThingModelDO(Long productId, String productKey, ThingModelEvent event) {
291   - return new IotProductThingModelDO()
292   - .setProductId(productId)
293   - .setProductKey(productKey)
294   - .setIdentifier(event.getIdentifier())
295   - .setName(event.getName())
296   - .setDescription(event.getDescription())
297   - .setType(IotProductThingModelTypeEnum.EVENT.getType())
298   - .setEvent(event);
  264 + return new IotProductThingModelDO().setProductId(productId).setProductKey(productKey)
  265 + .setIdentifier(event.getIdentifier()).setName(event.getName()).setDescription(event.getDescription())
  266 + .setType(IotProductThingModelTypeEnum.EVENT.getType()).setEvent(event);
299 267 }
300 268  
301 269 /**
302 270 * 构建服务功能对象
303 271 */
304 272 private IotProductThingModelDO buildServiceThingModelDO(Long productId, String productKey, ThingModelService service) {
305   - return new IotProductThingModelDO()
306   - .setProductId(productId)
307   - .setProductKey(productKey)
308   - .setIdentifier(service.getIdentifier())
309   - .setName(service.getName())
310   - .setDescription(service.getDescription())
311   - .setType(IotProductThingModelTypeEnum.SERVICE.getType())
312   - .setService(service);
  273 + return new IotProductThingModelDO().setProductId(productId).setProductKey(productKey)
  274 + .setIdentifier(service.getIdentifier()).setName(service.getName()).setDescription(service.getDescription())
  275 + .setType(IotProductThingModelTypeEnum.SERVICE.getType()).setService(service);
313 276 }
314 277  
315 278 /**
316 279 * 生成属性上报事件
317 280 */
318   - private ThingModelEvent generatePropertyPostEvent(List<IotProductThingModelDO> propertyList) {
319   - if (CollUtil.isEmpty(propertyList)) {
  281 + private ThingModelEvent generatePropertyPostEvent(List<IotProductThingModelDO> thingModelList) {
  282 + // 1.1 没有属性则不生成
  283 + if (CollUtil.isEmpty(thingModelList)) {
320 284 return null;
321 285 }
322 286  
323   - ThingModelEvent event = new ThingModelEvent()
324   - .setIdentifier("post")
325   - .setName("属性上报")
326   - .setType("info")
327   - .setDescription("属性上报事件")
328   - .setMethod("thing.event.property.post");
329   -
330   - // 将属性列表转换为事件的输出参数
331   - List<ThingModelArgument> outputData = new ArrayList<>();
332   - for (IotProductThingModelDO thingModel : propertyList) {
333   - ThingModelArgument arg = new ThingModelArgument()
334   - .setIdentifier(thingModel.getIdentifier())
335   - .setName(thingModel.getName())
336   - .setProperty(thingModel.getProperty())
337   - .setDescription(thingModel.getDescription())
338   - .setDirection("output"); // 设置为输出参数
339   - outputData.add(arg);
340   - }
341   - event.setOutputData(outputData);
342   - return event;
  287 + // 1.2 生成属性上报事件
  288 + return new ThingModelEvent().setIdentifier("post").setName("属性上报").setDescription("属性上报事件")
  289 + .setEventType(IotProductThingModelServiceEventTypeEnum.INFO.getType()).setMethod("thing.event.property.post")
  290 + .setOutputParams(buildInputOutputParam(thingModelList, IotProductThingModelParamDirectionEnum.OUTPUT));
343 291 }
344 292  
345 293 /**
346 294 * 生成属性设置服务
347 295 */
348   - private ThingModelService generatePropertySetService(List<IotProductThingModelDO> propertyList) {
349   - if (propertyList == null || propertyList.isEmpty()) {
350   - return null;
351   - }
352   -
353   - List<ThingModelArgument> inputData = new ArrayList<>();
354   - for (IotProductThingModelDO thingModel : propertyList) {
355   - ThingModelProperty property = thingModel.getProperty();
356   - if (IotProductThingModelAccessModeEnum.READ_WRITE.getMode().equals(property.getAccessMode())) {
357   - ThingModelArgument arg = new ThingModelArgument()
358   - .setIdentifier(property.getIdentifier())
359   - .setName(property.getName())
360   - .setProperty(property)
361   - .setDescription(property.getDescription())
362   - .setDirection("input"); // 设置为输入参数
363   - inputData.add(arg);
364   - }
365   - }
366   - if (inputData.isEmpty()) {
367   - // 如果没有可写属性,不生成属性设置服务
  296 + private ThingModelService generatePropertySetService(List<IotProductThingModelDO> thingModelList) {
  297 + // 1.1 过滤出所有可写属性
  298 + thingModelList = filterList(thingModelList, thingModel ->
  299 + IotProductThingModelAccessModeEnum.READ_WRITE.getMode().equals(thingModel.getProperty().getAccessMode()));
  300 + // 1.2 没有可写属性则不生成
  301 + if (CollUtil.isEmpty(thingModelList)) {
368 302 return null;
369 303 }
370 304  
371   - // 属性设置服务一般不需要输出参数
372   - return new ThingModelService()
373   - .setIdentifier("set")
374   - .setName("属性设置")
375   - .setCallType("async")
376   - .setDescription("属性设置服务")
377   - .setMethod("thing.service.property.set")
378   - .setInputData(inputData)
379   - // 属性设置服务一般不需要输出参数
380   - .setOutputData(new ArrayList<>());
  305 + // 2. 生成属性设置服务
  306 + return new ThingModelService().setIdentifier("set").setName("属性设置").setDescription("属性设置服务")
  307 + .setCallType(IotProductThingModelServiceCallTypeEnum.ASYNC.getType()).setMethod("thing.service.property.set")
  308 + .setInputParams(buildInputOutputParam(thingModelList, IotProductThingModelParamDirectionEnum.INPUT))
  309 + .setOutputParams(Collections.emptyList()); // 属性设置服务一般不需要输出参数
381 310 }
382 311  
383 312 /**
384 313 * 生成属性获取服务
385 314 */
386   - private ThingModelService generatePropertyGetService(List<IotProductThingModelDO> propertyList) {
387   - if (propertyList == null || propertyList.isEmpty()) {
  315 + private ThingModelService generatePropertyGetService(List<IotProductThingModelDO> thingModelList) {
  316 + // 1.1 没有属性则不生成
  317 + if (CollUtil.isEmpty(thingModelList)) {
388 318 return null;
389 319 }
390 320  
391   - List<ThingModelArgument> outputData = new ArrayList<>();
392   - for (IotProductThingModelDO thingModelDO : propertyList) {
393   - ThingModelProperty property = thingModelDO.getProperty();
394   - if (ObjectUtils.equalsAny(property.getAccessMode(),
395   - IotProductThingModelAccessModeEnum.READ_ONLY.getMode(), IotProductThingModelAccessModeEnum.READ_WRITE.getMode())) {
396   - ThingModelArgument arg = new ThingModelArgument()
397   - .setIdentifier(property.getIdentifier())
398   - .setName(property.getName())
399   - .setProperty(property)
400   - .setDescription(property.getDescription())
401   - .setDirection("output"); // 设置为输出参数
402   - outputData.add(arg);
403   - }
404   - }
405   - if (outputData.isEmpty()) {
406   - // 如果没有可读属性,不生成属性获取服务
407   - return null;
408   - }
  321 + // 1.2 生成属性获取服务
  322 + return new ThingModelService().setIdentifier("get").setName("属性获取").setDescription("属性获取服务")
  323 + .setCallType(IotProductThingModelServiceCallTypeEnum.ASYNC.getType()).setMethod("thing.service.property.get")
  324 + .setInputParams(buildInputOutputParam(thingModelList, IotProductThingModelParamDirectionEnum.INPUT))
  325 + .setOutputParams(buildInputOutputParam(thingModelList, IotProductThingModelParamDirectionEnum.OUTPUT));
  326 + }
409 327  
410   - ThingModelService service = new ThingModelService()
411   - .setIdentifier("get")
412   - .setName("属性获取")
413   - .setCallType("async")
414   - .setDescription("属性获取服务")
415   - .setMethod("thing.service.property.get");
416   -
417   - // 定义输入参数:属性标识符列表
418   - ThingModelArgument inputArg = new ThingModelArgument()
419   - .setIdentifier("properties")
420   - .setName("属性标识符列表")
421   - .setDescription("需要获取的属性标识符列表")
422   - .setDirection("input"); // 设置为输入参数
423   -
424   - // 创建数组类型,元素类型为文本类型(字符串)TODO @puhui999: 还得研究研究
425   - ThingModelArrayDataSpecs arrayType = new ThingModelArrayDataSpecs();
426   - arrayType.setDataType("array");
427   - inputArg.setProperty(new ThingModelProperty().setIdentifier(inputArg.getIdentifier()).setName(inputArg.getName())
428   - .setDescription(inputArg.getDescription()).setDataSpecs(arrayType));
429   -
430   - ThingModelDateOrTextDataSpecs textType = new ThingModelDateOrTextDataSpecs();
431   - textType.setDataType("text");
432   - inputArg.setProperty(new ThingModelProperty().setIdentifier(inputArg.getIdentifier()).setName(inputArg.getName())
433   - .setDescription(inputArg.getDescription()).setDataSpecs(textType));
434   -
435   - service.setInputData(Collections.singletonList(inputArg));
436   - service.setOutputData(outputData);
437   - return service;
  328 + /**
  329 + * 构建输入/输出参数列表
  330 + *
  331 + * @param thingModelList 属性列表
  332 + * @return 输入/输出参数列表
  333 + */
  334 + private List<ThingModelInputOutputParam> buildInputOutputParam(List<IotProductThingModelDO> thingModelList,
  335 + IotProductThingModelParamDirectionEnum directionEnum) {
  336 + return convertList(thingModelList, thingModel ->
  337 + BeanUtils.toBean(thingModel.getProperty(), ThingModelInputOutputParam.class).setParaOrder(0) // TODO @puhui999: 先搞个默认值看看怎么个事
  338 + .setDirection(directionEnum.getDirection()));
438 339 }
439 340  
440 341 }
... ...