reactor:【IoT 物联网】简化物模型的 CRUD 逻辑
This commit is contained in:
@@ -25,8 +25,6 @@ public interface IotThingModelMapper extends BaseMapperX<IotThingModelDO> {
|
|||||||
.likeIfPresent(IotThingModelDO::getName, reqVO.getName())
|
.likeIfPresent(IotThingModelDO::getName, reqVO.getName())
|
||||||
.eqIfPresent(IotThingModelDO::getType, reqVO.getType())
|
.eqIfPresent(IotThingModelDO::getType, reqVO.getType())
|
||||||
.eqIfPresent(IotThingModelDO::getProductId, reqVO.getProductId())
|
.eqIfPresent(IotThingModelDO::getProductId, reqVO.getProductId())
|
||||||
// TODO @芋艿:看看要不要加枚举
|
|
||||||
.notIn(IotThingModelDO::getIdentifier, "get", "set", "post")
|
|
||||||
.orderByDesc(IotThingModelDO::getId));
|
.orderByDesc(IotThingModelDO::getId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,8 +34,6 @@ public interface IotThingModelMapper extends BaseMapperX<IotThingModelDO> {
|
|||||||
.likeIfPresent(IotThingModelDO::getName, reqVO.getName())
|
.likeIfPresent(IotThingModelDO::getName, reqVO.getName())
|
||||||
.eqIfPresent(IotThingModelDO::getType, reqVO.getType())
|
.eqIfPresent(IotThingModelDO::getType, reqVO.getType())
|
||||||
.eqIfPresent(IotThingModelDO::getProductId, reqVO.getProductId())
|
.eqIfPresent(IotThingModelDO::getProductId, reqVO.getProductId())
|
||||||
// TODO @芋艿:看看要不要加枚举
|
|
||||||
.notIn(IotThingModelDO::getIdentifier, "get", "set", "post")
|
|
||||||
.orderByDesc(IotThingModelDO::getId));
|
.orderByDesc(IotThingModelDO::getId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,15 +57,6 @@ public interface IotThingModelMapper extends BaseMapperX<IotThingModelDO> {
|
|||||||
IotThingModelDO::getType, type);
|
IotThingModelDO::getType, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
default List<IotThingModelDO> selectListByProductIdAndIdentifiersAndTypes(Long productId,
|
|
||||||
List<String> identifiers,
|
|
||||||
List<Integer> types) {
|
|
||||||
return selectList(new LambdaQueryWrapperX<IotThingModelDO>()
|
|
||||||
.eq(IotThingModelDO::getProductId, productId)
|
|
||||||
.in(IotThingModelDO::getIdentifier, identifiers)
|
|
||||||
.in(IotThingModelDO::getType, types));
|
|
||||||
}
|
|
||||||
|
|
||||||
default IotThingModelDO selectByProductIdAndName(Long productId, String name) {
|
default IotThingModelDO selectByProductIdAndName(Long productId, String name) {
|
||||||
return selectOne(IotThingModelDO::getProductId, productId,
|
return selectOne(IotThingModelDO::getProductId, productId,
|
||||||
IotThingModelDO::getName, name);
|
IotThingModelDO::getName, name);
|
||||||
|
|||||||
@@ -5,11 +5,7 @@ import cn.hutool.core.util.ObjectUtil;
|
|||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.extra.spring.SpringUtil;
|
import cn.hutool.extra.spring.SpringUtil;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
|
||||||
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
|
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelEvent;
|
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelParam;
|
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelService;
|
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelListReqVO;
|
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelListReqVO;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO;
|
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO;
|
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO;
|
||||||
@@ -19,7 +15,6 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
|
|||||||
import cn.iocoder.yudao.module.iot.dal.mysql.thingmodel.IotThingModelMapper;
|
import cn.iocoder.yudao.module.iot.dal.mysql.thingmodel.IotThingModelMapper;
|
||||||
import cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants;
|
import cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants;
|
||||||
import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum;
|
import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum;
|
||||||
import cn.iocoder.yudao.module.iot.enums.thingmodel.*;
|
|
||||||
import cn.iocoder.yudao.module.iot.service.product.IotProductService;
|
import cn.iocoder.yudao.module.iot.service.product.IotProductService;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -29,10 +24,13 @@ import org.springframework.stereotype.Service;
|
|||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||||
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
|
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,12 +63,7 @@ public class IotThingModelServiceImpl implements IotThingModelService {
|
|||||||
IotThingModelDO thingModel = IotThingModelConvert.INSTANCE.convert(createReqVO);
|
IotThingModelDO thingModel = IotThingModelConvert.INSTANCE.convert(createReqVO);
|
||||||
thingModelMapper.insert(thingModel);
|
thingModelMapper.insert(thingModel);
|
||||||
|
|
||||||
// 3. 如果创建的是属性,需要更新默认的事件和服务
|
// 3. 删除缓存
|
||||||
if (Objects.equals(createReqVO.getType(), IotThingModelTypeEnum.PROPERTY.getType())) {
|
|
||||||
createDefaultEventsAndServices(createReqVO.getProductId(), createReqVO.getProductKey());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. 删除缓存
|
|
||||||
deleteThingModelListCache(createReqVO.getProductKey());
|
deleteThingModelListCache(createReqVO.getProductKey());
|
||||||
return thingModel.getId();
|
return thingModel.getId();
|
||||||
}
|
}
|
||||||
@@ -89,12 +82,7 @@ public class IotThingModelServiceImpl implements IotThingModelService {
|
|||||||
IotThingModelDO thingModel = IotThingModelConvert.INSTANCE.convert(updateReqVO);
|
IotThingModelDO thingModel = IotThingModelConvert.INSTANCE.convert(updateReqVO);
|
||||||
thingModelMapper.updateById(thingModel);
|
thingModelMapper.updateById(thingModel);
|
||||||
|
|
||||||
// 3. 如果更新的是属性,需要更新默认的事件和服务
|
// 3. 删除缓存
|
||||||
if (Objects.equals(updateReqVO.getType(), IotThingModelTypeEnum.PROPERTY.getType())) {
|
|
||||||
createDefaultEventsAndServices(updateReqVO.getProductId(), updateReqVO.getProductKey());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. 删除缓存
|
|
||||||
deleteThingModelListCache(updateReqVO.getProductKey());
|
deleteThingModelListCache(updateReqVO.getProductKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,12 +100,7 @@ public class IotThingModelServiceImpl implements IotThingModelService {
|
|||||||
// 2. 删除功能
|
// 2. 删除功能
|
||||||
thingModelMapper.deleteById(id);
|
thingModelMapper.deleteById(id);
|
||||||
|
|
||||||
// 3. 如果删除的是属性,需要更新默认的事件和服务
|
// 3. 删除缓存
|
||||||
if (Objects.equals(thingModel.getType(), IotThingModelTypeEnum.PROPERTY.getType())) {
|
|
||||||
createDefaultEventsAndServices(thingModel.getProductId(), thingModel.getProductKey());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. 删除缓存
|
|
||||||
deleteThingModelListCache(thingModel.getProductKey());
|
deleteThingModelListCache(thingModel.getProductKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,160 +204,6 @@ public class IotThingModelServiceImpl implements IotThingModelService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建默认的事件和服务
|
|
||||||
*
|
|
||||||
* @param productId 产品编号
|
|
||||||
* @param productKey 产品标识
|
|
||||||
*/
|
|
||||||
public void createDefaultEventsAndServices(Long productId, String productKey) {
|
|
||||||
// 1. 获取当前属性列表
|
|
||||||
List<IotThingModelDO> properties = thingModelMapper
|
|
||||||
.selectListByProductIdAndType(productId, IotThingModelTypeEnum.PROPERTY.getType());
|
|
||||||
|
|
||||||
// 2. 生成新的事件和服务列表
|
|
||||||
List<IotThingModelDO> newThingModels = new ArrayList<>();
|
|
||||||
// 2.1 生成属性上报事件
|
|
||||||
ThingModelEvent propertyPostEvent = generatePropertyPostEvent(properties);
|
|
||||||
if (propertyPostEvent != null) {
|
|
||||||
newThingModels.add(buildEventThingModel(productId, productKey, propertyPostEvent, "属性上报事件"));
|
|
||||||
}
|
|
||||||
// 2.2 生成属性设置服务
|
|
||||||
ThingModelService propertySetService = generatePropertySetService(properties);
|
|
||||||
if (propertySetService != null) {
|
|
||||||
newThingModels.add(buildServiceThingModel(productId, productKey, propertySetService, "属性设置服务"));
|
|
||||||
}
|
|
||||||
// 2.3 生成属性获取服务
|
|
||||||
ThingModelService propertyGetService = generatePropertyGetService(properties);
|
|
||||||
if (propertyGetService != null) {
|
|
||||||
newThingModels.add(buildServiceThingModel(productId, productKey, propertyGetService, "属性获取服务"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3.1 获取数据库中的默认的旧事件和服务列表
|
|
||||||
List<IotThingModelDO> oldThingModels = thingModelMapper.selectListByProductIdAndIdentifiersAndTypes(
|
|
||||||
productId,
|
|
||||||
Arrays.asList("post", "set", "get"),
|
|
||||||
Arrays.asList(IotThingModelTypeEnum.EVENT.getType(), IotThingModelTypeEnum.SERVICE.getType())
|
|
||||||
);
|
|
||||||
// 3.2 创建默认的事件和服务
|
|
||||||
createDefaultEventsAndServices(oldThingModels, newThingModels);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建默认的事件和服务
|
|
||||||
*/
|
|
||||||
private void createDefaultEventsAndServices(List<IotThingModelDO> oldThingModels,
|
|
||||||
List<IotThingModelDO> newThingModels) {
|
|
||||||
// 使用 diffList 方法比较新旧列表
|
|
||||||
List<List<IotThingModelDO>> diffResult = diffList(oldThingModels, newThingModels,
|
|
||||||
(oldVal, newVal) -> {
|
|
||||||
// 继续使用 identifier 和 type 进行比较:这样可以准确地匹配对应的功能对象。
|
|
||||||
boolean same = Objects.equals(oldVal.getIdentifier(), newVal.getIdentifier())
|
|
||||||
&& Objects.equals(oldVal.getType(), newVal.getType());
|
|
||||||
if (same) {
|
|
||||||
newVal.setId(oldVal.getId()); // 设置编号
|
|
||||||
}
|
|
||||||
return same;
|
|
||||||
});
|
|
||||||
// 批量添加、修改、删除
|
|
||||||
if (CollUtil.isNotEmpty(diffResult.get(0))) {
|
|
||||||
thingModelMapper.insertBatch(diffResult.get(0));
|
|
||||||
}
|
|
||||||
if (CollUtil.isNotEmpty(diffResult.get(1))) {
|
|
||||||
thingModelMapper.updateBatch(diffResult.get(1));
|
|
||||||
}
|
|
||||||
if (CollUtil.isNotEmpty(diffResult.get(2))) {
|
|
||||||
thingModelMapper.deleteByIds(convertSet(diffResult.get(2), IotThingModelDO::getId));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构建事件功能对象
|
|
||||||
*/
|
|
||||||
private IotThingModelDO buildEventThingModel(Long productId, String productKey,
|
|
||||||
ThingModelEvent event, String description) {
|
|
||||||
return new IotThingModelDO().setProductId(productId).setProductKey(productKey)
|
|
||||||
.setIdentifier(event.getIdentifier()).setName(event.getName()).setDescription(description)
|
|
||||||
.setType(IotThingModelTypeEnum.EVENT.getType()).setEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构建服务功能对象
|
|
||||||
*/
|
|
||||||
private IotThingModelDO buildServiceThingModel(Long productId, String productKey,
|
|
||||||
ThingModelService service, String description) {
|
|
||||||
return new IotThingModelDO().setProductId(productId).setProductKey(productKey)
|
|
||||||
.setIdentifier(service.getIdentifier()).setName(service.getName()).setDescription(description)
|
|
||||||
.setType(IotThingModelTypeEnum.SERVICE.getType()).setService(service);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO @haohao:是不是不用生成这个?目前属性上报,是个批量接口
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成属性上报事件
|
|
||||||
*/
|
|
||||||
private ThingModelEvent generatePropertyPostEvent(List<IotThingModelDO> thingModels) {
|
|
||||||
// 没有属性则不生成
|
|
||||||
if (CollUtil.isEmpty(thingModels)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成属性上报事件
|
|
||||||
return new ThingModelEvent().setIdentifier("post").setName("属性上报").setMethod("thing.event.property.post")
|
|
||||||
.setType(IotThingModelServiceEventTypeEnum.INFO.getType())
|
|
||||||
.setOutputParams(buildInputOutputParam(thingModels, IotThingModelParamDirectionEnum.OUTPUT));
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO @haohao:是不是不用生成这个?目前属性上报,是个批量接口
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成属性设置服务
|
|
||||||
*/
|
|
||||||
private ThingModelService generatePropertySetService(List<IotThingModelDO> thingModels) {
|
|
||||||
// 1.1 过滤出所有可写属性
|
|
||||||
thingModels = filterList(thingModels, thingModel ->
|
|
||||||
IotThingModelAccessModeEnum.READ_WRITE.getMode().equals(thingModel.getProperty().getAccessMode()));
|
|
||||||
// 1.2 没有可写属性则不生成
|
|
||||||
if (CollUtil.isEmpty(thingModels)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 生成属性设置服务
|
|
||||||
return new ThingModelService().setIdentifier("set").setName("属性设置").setMethod("thing.service.property.set")
|
|
||||||
.setCallType(IotThingModelServiceCallTypeEnum.ASYNC.getType())
|
|
||||||
.setInputParams(buildInputOutputParam(thingModels, IotThingModelParamDirectionEnum.INPUT))
|
|
||||||
.setOutputParams(Collections.emptyList()); // 属性设置服务一般不需要输出参数
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成属性获取服务
|
|
||||||
*/
|
|
||||||
private ThingModelService generatePropertyGetService(List<IotThingModelDO> thingModels) {
|
|
||||||
// 1.1 没有属性则不生成
|
|
||||||
if (CollUtil.isEmpty(thingModels)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1.2 生成属性获取服务
|
|
||||||
return new ThingModelService().setIdentifier("get").setName("属性获取").setMethod("thing.service.property.get")
|
|
||||||
.setCallType(IotThingModelServiceCallTypeEnum.ASYNC.getType())
|
|
||||||
.setInputParams(buildInputOutputParam(thingModels, IotThingModelParamDirectionEnum.INPUT))
|
|
||||||
.setOutputParams(buildInputOutputParam(thingModels, IotThingModelParamDirectionEnum.OUTPUT));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构建输入/输出参数列表
|
|
||||||
*
|
|
||||||
* @param thingModels 属性列表
|
|
||||||
* @return 输入/输出参数列表
|
|
||||||
*/
|
|
||||||
private List<ThingModelParam> buildInputOutputParam(List<IotThingModelDO> thingModels,
|
|
||||||
IotThingModelParamDirectionEnum direction) {
|
|
||||||
return convertList(thingModels, thingModel ->
|
|
||||||
BeanUtils.toBean(thingModel.getProperty(), ThingModelParam.class).setParaOrder(0) // TODO @puhui999: 先搞个默认值看看怎么个事
|
|
||||||
.setDirection(direction.getDirection()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deleteThingModelListCache(String productKey) {
|
private void deleteThingModelListCache(String productKey) {
|
||||||
// 保证 Spring AOP 触发
|
// 保证 Spring AOP 触发
|
||||||
getSelf().deleteThingModelListCache0(productKey);
|
getSelf().deleteThingModelListCache0(productKey);
|
||||||
|
|||||||
Reference in New Issue
Block a user