Compare commits

...

11 Commits
plp ... main

@ -1,5 +1,6 @@
package cn.iocoder.yudao.framework.common.util.opc; package cn.iocoder.yudao.framework.common.util.opc;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient; import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.sdk.client.api.config.OpcUaClientConfig; import org.eclipse.milo.opcua.sdk.client.api.config.OpcUaClientConfig;
import org.eclipse.milo.opcua.sdk.client.api.config.OpcUaClientConfigBuilder; import org.eclipse.milo.opcua.sdk.client.api.config.OpcUaClientConfigBuilder;
@ -24,6 +25,7 @@ import java.util.function.Predicate;
* OPC UA - Eclipse Milo 0.6.9 * OPC UA - Eclipse Milo 0.6.9
* OPC UA * OPC UA
*/ */
@Slf4j
public class OpcUtils { public class OpcUtils {
// 静态成员变量,所有实例共享 // 静态成员变量,所有实例共享
@ -46,14 +48,15 @@ public class OpcUtils {
public static boolean connect(String url, String username, String password, int timeoutSeconds) { public static boolean connect(String url, String username, String password, int timeoutSeconds) {
if (isConnected) { if (isConnected) {
System.out.println(LOG_PREFIX + "客户端已连接,无需重复连接"); log.info(" {} 客户端已连接,无需重复连接",LOG_PREFIX);
return true; return true;
} }
serverUrl = url; serverUrl = url;
try { try {
System.out.println(LOG_PREFIX + "正在连接到OPC UA服务器: " + url);
log.info(" {} 正在连接到OPC UA服务器 {}",LOG_PREFIX,url);
// 提取主机和端口 // 提取主机和端口
final String targetHost = extractHostFromUrl(url); final String targetHost = extractHostFromUrl(url);
@ -62,6 +65,7 @@ public class OpcUtils {
System.out.println(LOG_PREFIX + "目标主机: " + targetHost + ", 端口: " + targetPort + ", 路径: " + path); System.out.println(LOG_PREFIX + "目标主机: " + targetHost + ", 端口: " + targetPort + ", 路径: " + path);
// 将主机名解析为IP地址 // 将主机名解析为IP地址
final String ipAddress = resolveToIpAddress(targetHost); final String ipAddress = resolveToIpAddress(targetHost);
System.out.println(LOG_PREFIX + "解析为IP地址: " + ipAddress); System.out.println(LOG_PREFIX + "解析为IP地址: " + ipAddress);

@ -54,11 +54,11 @@ public class ErpProductController {
ErpProductPageReqVO productPageReqVO = new ErpProductPageReqVO(); ErpProductPageReqVO productPageReqVO = new ErpProductPageReqVO();
productPageReqVO.setName(createReqVO.getName()); productPageReqVO.setName(createReqVO.getName());
if (!productMapper.selectProductExist(productPageReqVO).getList().isEmpty()) { if (!productMapper.selectProductExist(productPageReqVO).getList().isEmpty()) {
return error(400,"名称不能重复"); return error(400,"名称+规格不能重复");
} }
productPageReqVO = new ErpProductPageReqVO(); productPageReqVO = new ErpProductPageReqVO();
productPageReqVO.setCode(createReqVO.getBarCode()); productPageReqVO.setCode(createReqVO.getBarCode());
if (!productMapper.selectProductExist(productPageReqVO).getList().isEmpty()) { if (!productMapper.selectProductCodeExist(productPageReqVO).getList().isEmpty()) {
return error(400,"编码不能重复"); return error(400,"编码不能重复");
} }
return success(productService.createProduct(createReqVO)); return success(productService.createProduct(createReqVO));

@ -115,4 +115,12 @@ public class ErpProductUnitController {
} }
@GetMapping("/flag-list")
@Operation(summary = "获得产品主单位列表")
public CommonResult<List<ErpProductUnitDO>> getProductUnitListByFlag() {
List<ErpProductUnitDO> productUnitDOList = productUnitService.getProductUnitListByFlag();
return success(productUnitDOList);
}
} }

@ -27,4 +27,7 @@ public class ErpProductPageReqVO extends PageParam {
@Schema(description = "产品编号", example = "11161") @Schema(description = "产品编号", example = "11161")
private String code; private String code;
@Schema(description = "产品规格", example = "红色")
private String standard;
} }

@ -24,4 +24,13 @@ public class ErpProductUnitSaveReqVO {
@InEnum(CommonStatusEnum.class) @InEnum(CommonStatusEnum.class)
private Integer status; private Integer status;
@Schema(description = "是否主单位", example = "芋艿")
private String primaryFlag;
@Schema(description = "关联主单位id", example = "芋艿")
private Long primaryId;
@Schema(description = "换算比例", example = "芋艿")
private Double changeRate;
} }

@ -29,13 +29,20 @@ public interface ErpProductMapper extends BaseMapperX<ErpProductDO> {
.orderByDesc(ErpProductDO::getId)); .orderByDesc(ErpProductDO::getId));
} }
default PageResult<ErpProductDO> selectProductExist(ErpProductPageReqVO reqVO) { default PageResult<ErpProductDO> selectProductCodeExist(ErpProductPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<ErpProductDO>() return selectPage(reqVO, new LambdaQueryWrapperX<ErpProductDO>()
.eqIfPresent(ErpProductDO::getName, reqVO.getName()) .eqIfPresent(ErpProductDO::getName, reqVO.getName())
.eqIfPresent(ErpProductDO::getBarCode, reqVO.getCode()) .eqIfPresent(ErpProductDO::getBarCode, reqVO.getCode())
.orderByAsc(ErpProductDO::getId)); .orderByAsc(ErpProductDO::getId));
} }
default PageResult<ErpProductDO> selectProductExist(ErpProductPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<ErpProductDO>()
.eqIfPresent(ErpProductDO::getName, reqVO.getName())
.eqIfPresent(ErpProductDO::getStandard, reqVO.getStandard())
.orderByAsc(ErpProductDO::getId));
}
default Long selectCountByCategoryId(Long categoryId) { default Long selectCountByCategoryId(Long categoryId) {
return selectCount(ErpProductDO::getCategoryId, categoryId); return selectCount(ErpProductDO::getCategoryId, categoryId);
} }

@ -92,6 +92,13 @@ public interface ErpProductUnitService {
*/ */
List<ErpProductUnitDO> getProductUnitList(); List<ErpProductUnitDO> getProductUnitList();
/**
*
*
* @return
*/
List<ErpProductUnitDO> getProductUnitListByFlag();
/** /**
* *
* *

@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUn
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO;
import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductUnitMapper; import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductUnitMapper;
import cn.iocoder.yudao.module.erp.framework.bean.ProductUnitEnum; import cn.iocoder.yudao.module.erp.framework.bean.ProductUnitEnum;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -52,7 +53,7 @@ public class ErpProductUnitServiceImpl implements ErpProductUnitService {
updateReqVO.getId().equals(ProductUnitEnum.Kilogram.getUnitId()) updateReqVO.getId().equals(ProductUnitEnum.Kilogram.getUnitId())
|| updateReqVO.getId().equals(ProductUnitEnum.Gram.getUnitId()) || updateReqVO.getId().equals(ProductUnitEnum.Gram.getUnitId())
|| updateReqVO.getId().equals(ProductUnitEnum.Each.getUnitId())){ || updateReqVO.getId().equals(ProductUnitEnum.Each.getUnitId())){
throw exception(new ErrorCode(500,"内置单位不允许更改")); throw exception(new ErrorCode(40001,"内置单位不允许更改"));
} }
// 1.1 校验存在 // 1.1 校验存在
validateProductUnitExists(updateReqVO.getId()); validateProductUnitExists(updateReqVO.getId());
@ -129,4 +130,10 @@ public class ErpProductUnitServiceImpl implements ErpProductUnitService {
public ErpProductUnitDO getProductUnitByName(String name) { public ErpProductUnitDO getProductUnitByName(String name) {
return productUnitMapper.selectByName(name); return productUnitMapper.selectByName(name);
} }
@Override
public List<ErpProductUnitDO> getProductUnitListByFlag() {
QueryWrapper<ErpProductUnitDO> wrapper = new QueryWrapper<>();
wrapper.eq("primary_flag", "Y");
return productUnitMapper.selectList(wrapper);
}
} }

@ -52,6 +52,12 @@
<artifactId>yudao-spring-boot-starter-mybatis</artifactId> <artifactId>yudao-spring-boot-starter-mybatis</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.cronutils</groupId>
<artifactId>cron-utils</artifactId>
<version>9.2.0</version>
</dependency>
<!-- Test 测试相关 --> <!-- Test 测试相关 -->
<dependency> <dependency>
<groupId>cn.iocoder.boot</groupId> <groupId>cn.iocoder.boot</groupId>

@ -1,11 +1,14 @@
// DeviceTask.java - 原有设备任务 // DeviceTask.java - 原有设备任务
package cn.iocoder.yudao.module.iot.controller.admin.device.scheduled.coretask; package cn.iocoder.yudao.module.iot.controller.admin.device.scheduled.coretask;
import cn.iocoder.yudao.framework.common.enums.DeviceConnectionStatusEnum;
import cn.iocoder.yudao.framework.common.util.opc.OpcUtils; import cn.iocoder.yudao.framework.common.util.opc.OpcUtils;
import cn.iocoder.yudao.module.iot.controller.admin.device.enums.DeviceBasicStatusEnum; import cn.iocoder.yudao.module.iot.controller.admin.device.enums.DeviceBasicStatusEnum;
import cn.iocoder.yudao.module.iot.controller.admin.device.enums.DeviceStatusEnum; import cn.iocoder.yudao.module.iot.controller.admin.device.enums.DeviceStatusEnum;
import cn.iocoder.yudao.module.iot.controller.admin.device.enums.TaskTypeEnum; import cn.iocoder.yudao.module.iot.controller.admin.device.enums.TaskTypeEnum;
import cn.iocoder.yudao.module.iot.controller.admin.device.scheduled.core.Task; import cn.iocoder.yudao.module.iot.controller.admin.device.scheduled.core.Task;
import cn.iocoder.yudao.module.iot.controller.admin.device.scheduled.scheduler.TaskSchedulerManager;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.DeviceSaveReqVO;
import cn.iocoder.yudao.module.iot.controller.admin.devicemodelrules.vo.PointRulesRespVO; import cn.iocoder.yudao.module.iot.controller.admin.devicemodelrules.vo.PointRulesRespVO;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.devicecontactmodel.DeviceContactModelDO; import cn.iocoder.yudao.module.iot.dal.dataobject.devicecontactmodel.DeviceContactModelDO;
@ -17,6 +20,7 @@ import cn.iocoder.yudao.module.iot.dal.mysql.devicecontactmodel.DeviceContactMod
import cn.iocoder.yudao.module.iot.dal.mysql.deviceoperationrecord.DeviceOperationRecordMapper; import cn.iocoder.yudao.module.iot.dal.mysql.deviceoperationrecord.DeviceOperationRecordMapper;
import cn.iocoder.yudao.module.iot.dal.mysql.devicepointrules.DevicePointRulesMapper; import cn.iocoder.yudao.module.iot.dal.mysql.devicepointrules.DevicePointRulesMapper;
import cn.iocoder.yudao.module.iot.dal.mysql.devicewarinningrecord.DeviceWarinningRecordMapper; import cn.iocoder.yudao.module.iot.dal.mysql.devicewarinningrecord.DeviceWarinningRecordMapper;
import cn.iocoder.yudao.module.iot.service.device.DeviceService;
import cn.iocoder.yudao.module.iot.service.device.TDengineService; import cn.iocoder.yudao.module.iot.service.device.TDengineService;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@ -26,6 +30,7 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.annotation.Resource; import javax.annotation.Resource;
@ -48,6 +53,10 @@ public class DeviceTask implements Task {
@Resource @Resource
private TDengineService tDengineService; private TDengineService tDengineService;
@Resource
@Lazy
private DeviceService deviceService;
@Resource @Resource
private DevicePointRulesMapper devicePointRulesMapper; private DevicePointRulesMapper devicePointRulesMapper;
@ -57,6 +66,10 @@ public class DeviceTask implements Task {
@Resource @Resource
private DeviceWarinningRecordMapper deviceWarinningRecordMapper; private DeviceWarinningRecordMapper deviceWarinningRecordMapper;
@Resource
@Lazy
private TaskSchedulerManager taskSchedulerManager;
@Override @Override
public String getTaskType() { public String getTaskType() {
return TaskTypeEnum.DEVICE.getCode(); return TaskTypeEnum.DEVICE.getCode();
@ -103,13 +116,6 @@ public class DeviceTask implements Task {
logger.info("执行设备任务任务ID: {}, 参数: {}, 时间: {}", logger.info("执行设备任务任务ID: {}, 参数: {}, 时间: {}",
taskId, taskParam, currentTime); taskId, taskParam, currentTime);
// 解析参数,假设格式为 deviceId:deviceCode
// String[] params = taskParam.split(":");
// if (params.length >= 2) {
// Long deviceId = Long.parseLong(params[0]);
// String deviceCode = params[1];
// executeDeviceLogic(deviceId, deviceCode);
// }
executeDeviceLogic(taskId,taskParam); executeDeviceLogic(taskId,taskParam);
@ -148,32 +154,6 @@ public class DeviceTask implements Task {
OpcUtils.disconnect(); OpcUtils.disconnect();
} }
/**
*
*/
// private void executeDeviceLogic(Long sourceDeviceId, String param) {
// logger.info("执行设备逻辑源设备ID: {},参数: {}", sourceDeviceId, param);
//
// // 1. 计算实际设备ID
// Long deviceId = sourceDeviceId - 1000000L;
// logger.info("处理后设备ID: {}", deviceId);
//
// if (deviceId == null) {
// throw new RuntimeException("设备ID不能为空");
// }
//
// // 2. 获取设备信息
// DeviceDO device = getDeviceInfo(deviceId);
//
// // 3. 连接OPC服务器
// connectOpcServer(device);
//
// // 4. 处理数据读取和入库
// processDeviceData(deviceId, device);
//
// // 5. 断开连接
// OpcUtils.disconnect();
// }
/** /**
* *
@ -199,25 +179,95 @@ public class DeviceTask implements Task {
String username = StringUtils.defaultString(device.getUsername()); String username = StringUtils.defaultString(device.getUsername());
String password = StringUtils.defaultString(device.getPassword()); String password = StringUtils.defaultString(device.getPassword());
boolean connected = OpcUtils.connect(device.getUrl(), username, password, 10); boolean connected = false;
if (!connected) {
throw new RuntimeException("连接OPC服务器失败URL: " + device.getUrl());
try {
connected = OpcUtils.connect(device.getUrl(), username, password, 10);
if (!connected) {
log.error("设备 {} 连接OPC服务器失败URL: {}", device.getId(), device.getUrl());
device.setStatus(String.valueOf(DeviceConnectionStatusEnum.DISCONNECTED.getStatus()));
deviceMapper.updateById(device);
taskSchedulerManager.stopDeviceTask(device.getId());
DeviceOperationRecordDO deviceOperationRecordDO = new DeviceOperationRecordDO();
deviceOperationRecordDO.setDeviceId(device.getId());
deviceOperationRecordDO.setRule(DeviceStatusEnum.OFFLINE.getCode());
//TODO 默认内置管理员
deviceOperationRecordDO.setCreator("1");
deviceOperationRecordDO.setUpdater("1");
deviceOperationRecordMapper.insert(deviceOperationRecordDO);
//抛出异常终止任务
throw new RuntimeException("连接opcuv服务器异常");
}
log.info("设备 {} 成功连接OPC服务器URL: {}", device.getId(), device.getUrl());
} catch (Exception e) {
log.error("设备 {} 连接OPC服务器异常URL: {}", device.getId(), device.getUrl(), e);
device.setStatus(String.valueOf(DeviceConnectionStatusEnum.DISCONNECTED.getStatus()));
deviceMapper.updateById(device);
taskSchedulerManager.stopDeviceTask(device.getId());
DeviceOperationRecordDO deviceOperationRecordDO = new DeviceOperationRecordDO();
deviceOperationRecordDO.setDeviceId(device.getId());
deviceOperationRecordDO.setRule(DeviceStatusEnum.OFFLINE.getCode());
//TODO 默认内置管理员
deviceOperationRecordDO.setCreator("1");
deviceOperationRecordDO.setUpdater("1");
deviceOperationRecordMapper.insert(deviceOperationRecordDO);
//抛出异常终止任务
throw new RuntimeException(e);
} }
} }
/** /**
* *
*/ */
private void processDeviceData(Long deviceId, DeviceDO device) { private void processDeviceData(Long deviceId, DeviceDO device) {
DeviceDO deviceDO = deviceMapper.selectById(deviceId);
// 1. 查询点位配置 // 1. 查询点位配置
List<DeviceContactModelDO> points = getDevicePoints(deviceId); List<DeviceContactModelDO> points = getDevicePoints(deviceId);
if (CollectionUtils.isEmpty(points)) { if (CollectionUtils.isEmpty(points)) {
logger.warn("设备 {} 未配置点位", deviceId); logger.warn("设备 {} 未配置点位", deviceId);
//更新状态为待机中
DeviceOperationRecordDO record = new DeviceOperationRecordDO();
record.setDeviceId(device.getId());
record.setRule(DeviceStatusEnum.STANDBY.getCode());
record.setTotalStandbyTime(deviceDO.getSampleCycle());
//TODO 创建人和更新人为内置默认管理员
record.setCreator("1");
record.setUpdater("1");
deviceOperationRecordMapper.insert(record);
return; return;
} }
logger.info("设备 {} 需要读取 {} 个点位", deviceId, points.size()); logger.info("设备 {} 需要读取 {} 个点位", deviceId, points.size());
DevicePointRulesDO devicePointRulesDO = devicePointRulesMapper.selectOne(Wrappers.<DevicePointRulesDO>lambdaQuery()
.eq(DevicePointRulesDO::getDeviceId, deviceId)
.eq(DevicePointRulesDO::getIdentifier, DeviceBasicStatusEnum.RUNNING));
if(devicePointRulesDO !=null && devicePointRulesDO.getFieldRule() == null ){
//更新状态为待机中
DeviceOperationRecordDO record = new DeviceOperationRecordDO();
record.setDeviceId(device.getId());
record.setRule(DeviceStatusEnum.STANDBY.getCode());
record.setTotalStandbyTime(deviceDO.getSampleCycle());
//TODO 创建人和更新人为内置默认管理员
record.setCreator("1");
record.setUpdater("1");
deviceOperationRecordMapper.insert(record);
}
// 2. 读取并处理数据 // 2. 读取并处理数据
int successCount = 0; int successCount = 0;
List<DeviceContactModelDO> validDataList = new ArrayList<>(); List<DeviceContactModelDO> validDataList = new ArrayList<>();
@ -333,9 +383,9 @@ public class DeviceTask implements Task {
// 2. 遍历规则 // 2. 遍历规则
for (DevicePointRulesDO devicePointRulesDO : devicePointRulesDOList) { for (DevicePointRulesDO devicePointRulesDO : devicePointRulesDOList) {
if (StringUtils.isBlank(devicePointRulesDO.getFieldRule())) { if (StringUtils.isBlank(devicePointRulesDO.getFieldRule())) {
continue; continue;
} }
// 3. 解析规则列表 // 3. 解析规则列表
List<PointRulesRespVO> pointRulesVOList = JSON.parseArray( List<PointRulesRespVO> pointRulesVOList = JSON.parseArray(

@ -42,9 +42,12 @@ public class DeviceModelAttributeRespVO {
private String address; private String address;
@Schema(description = "单位") @Schema(description = "单位")
@ExcelProperty("单位")
private String dataUnit; private String dataUnit;
@Schema(description = "单位")
@ExcelProperty("单位")
private String dataUnitName;
@Schema(description = "倍率") @Schema(description = "倍率")
@ExcelProperty("倍率") @ExcelProperty("倍率")
private Double ratio; private Double ratio;

@ -56,4 +56,7 @@ public class RecipeRespVO {
// @ExcelProperty("关联设备ID") // @ExcelProperty("关联设备ID")
private Long deviceId; private Long deviceId;
@Schema(description = "设备Id")
private Long machineId;
} }

@ -37,4 +37,7 @@ public class RecipeSaveReqVO {
@Schema(description = "数据单位") @Schema(description = "数据单位")
private String dataUnit; private String dataUnit;
@Schema(description = "设备Id")
private Long machineId;
} }

@ -1,9 +1,15 @@
package cn.iocoder.yudao.module.iot.controller.admin.recipedevicerecord; package cn.iocoder.yudao.module.iot.controller.admin.recipedevicerecord;
import cn.iocoder.yudao.framework.common.util.opc.OpcUtils;
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.DeviceRespVO;
import cn.iocoder.yudao.module.iot.dal.dataobject.devicecontactmodel.DeviceContactModelDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.recipe.RecipeDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.recipeplandetail.RecipePlanDetailDO; import cn.iocoder.yudao.module.iot.dal.dataobject.recipeplandetail.RecipePlanDetailDO;
import cn.iocoder.yudao.module.iot.service.device.DeviceService; import cn.iocoder.yudao.module.iot.service.device.DeviceService;
import cn.iocoder.yudao.module.iot.service.devicecontactmodel.DeviceContactModelService;
import cn.iocoder.yudao.module.iot.service.recipe.RecipeService; import cn.iocoder.yudao.module.iot.service.recipe.RecipeService;
import cn.iocoder.yudao.module.iot.service.recipeplandetail.RecipePlanDetailService; import cn.iocoder.yudao.module.iot.service.recipeplandetail.RecipePlanDetailService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -16,17 +22,23 @@ import javax.validation.*;
import javax.servlet.http.*; import javax.servlet.http.*;
import java.util.*; import java.util.*;
import java.io.IOException; import java.io.IOException;
import java.util.function.Function;
import java.util.stream.Collectors;
import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*; import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DEVICE_NOT_EXISTS;
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.RECIPE_NOT_EXISTS;
import cn.iocoder.yudao.module.iot.controller.admin.recipedevicerecord.vo.*; import cn.iocoder.yudao.module.iot.controller.admin.recipedevicerecord.vo.*;
import cn.iocoder.yudao.module.iot.dal.dataobject.recipedevicerecord.RecipeDeviceRecordDO; import cn.iocoder.yudao.module.iot.dal.dataobject.recipedevicerecord.RecipeDeviceRecordDO;
@ -73,6 +85,9 @@ public class RecipeDeviceRecordController {
@Resource @Resource
private DeviceService deviceService; private DeviceService deviceService;
@Resource
private DeviceContactModelService deviceContactModelService;
@PostMapping("/create") @PostMapping("/create")
@ -134,7 +149,6 @@ public class RecipeDeviceRecordController {
/** /**
* *
* @param recipeId ID * @param recipeId ID
* @param pointList [{id: 1, refer: "参考值1"}, {id: 2, refer: "参考值2"}]
* @return * @return
* @throws JsonProcessingException JSON * @throws JsonProcessingException JSON
*/ */
@ -145,37 +159,65 @@ public class RecipeDeviceRecordController {
@RequestParam("id") Long recipeId) { @RequestParam("id") Long recipeId) {
RecipePlanDetailDO recipePlanDetailDO = recipePlanDetailService.getRecipePlanDetail(recipeId); try {
//RecipeRespVO recipeRespVO = recipeService.getRecipeWithDeviceId(recipePlanDetailDO.getRecipeId()); RecipePlanDetailDO recipePlanDetailDO = recipePlanDetailService.getRecipePlanDetail(recipeId);
//RecipeRespVO recipeRespVO = recipeService.getRecipeWithDeviceId(recipePlanDetailDO.getRecipeId());
//RecipeDO recipeDO = recipeService.getRecipe(recipePlanDetailDO.getRecipeId());
// ========== 第一步:查询配方关联的点位属性信息 ==========
// 1.1 根据recipeId查询iot_recipe_device_attribute表记录
//RecipeDO recipeDO = recipeService.getRecipe(recipePlanDetailDO.getRecipeId()); recipePlanDetailDO.setRecipeId(recipeId);
// ========== 第一步:查询配方关联的点位属性信息 ========== List<RecipeDeviceAttributeDO> attributeList = recipeDeviceAttributeService.getByRecipeId(recipePlanDetailDO.getRecipeId());
// 1.1 根据recipeId查询iot_recipe_device_attribute表记录
recipePlanDetailDO.setRecipeId(32L); //先删除在添加
List<RecipeDeviceAttributeDO> attributeList = recipeDeviceAttributeService.getByRecipeId(recipePlanDetailDO.getRecipeId()); List<RecipeDeviceRecordDO> recipeDeviceRecordDOS = recipeDeviceRecordService.getListByRecipeId(recipeId);
// if (CollectionUtils.isEmpty(attributeList)) { if (!recipeDeviceRecordDOS.isEmpty()){
// return success(false); // 无关联属性,直接返回 recipeDeviceRecordService.deleteByIds(recipeDeviceRecordDOS);
// } }
Map<Long, Map<String, Object>> deviceDataMap = deviceService.createDeviceDataMap(103L);//recipeRespVO.getDeviceId() RecipeDO recipe = recipeService.getRecipe(recipeId);
if (recipe == null){
throw exception(RECIPE_NOT_EXISTS);
}
DeviceRespVO device = deviceService.getDevice(recipe.getMachineId());
if (device== null ){
throw exception(DEVICE_NOT_EXISTS);
}
for (RecipeDeviceAttributeDO attributeDO : attributeList) { Map<Long, DeviceContactModelDO> deviceContactModelMap = new HashMap<>();
Map<String, Object> data = deviceDataMap.get(attributeDO.getAttributeId()); List<DeviceContactModelDO> deviceContactModelDOS = deviceContactModelService.selectListByDeviceId(device.getId());
if (data != null ) { if (!deviceContactModelDOS.isEmpty()){
deviceContactModelMap = deviceContactModelDOS.stream()
.collect(Collectors.toMap(
DeviceContactModelDO::getId,
Function.identity()
));
}
OpcUtils.connect(device.getUrl(),device.getUsername(),device.getPassword(),10);
for (RecipeDeviceAttributeDO attributeDO : attributeList) {
DeviceContactModelDO deviceContactModelDO = deviceContactModelMap.get(attributeDO.getAttributeId());
if (deviceContactModelDO == null){
continue;
}
// 创建 // 创建
RecipeDeviceRecordDO recipeDeviceRecordDO = new RecipeDeviceRecordDO(); RecipeDeviceRecordDO recipeDeviceRecordDO = new RecipeDeviceRecordDO();
recipeDeviceRecordDO.setRecipeId(recipeId); recipeDeviceRecordDO.setRecipeId(recipeId);
recipeDeviceRecordDO.setAttributeCode(attributeDO.getAttributeName()); recipeDeviceRecordDO.setAttributeCode(deviceContactModelDO.getAttributeName());
recipeDeviceRecordDO.setDataType(attributeDO.getDataType()); recipeDeviceRecordDO.setDataType(deviceContactModelDO.getDataType());
recipeDeviceRecordDO.setDataUnit(attributeDO.getDataUnit()); recipeDeviceRecordDO.setDataUnit(deviceContactModelDO.getDataUnit());
if (data.get("addressValue") != null && data.get("addressValue").toString() != null) { recipeDeviceRecordDO.setValue((String) OpcUtils.readValue(deviceContactModelDO.getAddress()));
recipeDeviceRecordDO.setValue(data.get("addressValue").toString());
}
recipeDeviceRecordService.createRecipeDeviceRecord(BeanUtils.toBean(recipeDeviceRecordDO, RecipeDeviceRecordSaveReqVO.class)); recipeDeviceRecordService.createRecipeDeviceRecord(BeanUtils.toBean(recipeDeviceRecordDO, RecipeDeviceRecordSaveReqVO.class));
} }
} finally {
OpcUtils.disconnect();
} }
return success(true); return success(true);
} }

@ -52,4 +52,5 @@ public class RecipeDeviceRecordPageReqVO extends PageParam {
@Schema(description = "配方id", example = "32535") @Schema(description = "配方id", example = "32535")
private Long recipeId; private Long recipeId;
} }

@ -25,7 +25,7 @@ public class RecipePlanDetailSaveReqVO {
private Long recipeId; private Long recipeId;
@Schema(description = "关联计划关联mes_plan表的id", requiredMode = Schema.RequiredMode.REQUIRED, example = "28398") @Schema(description = "关联计划关联mes_plan表的id", requiredMode = Schema.RequiredMode.REQUIRED, example = "28398")
@NotNull(message = "关联计划关联mes_plan表的id不能为空") // @NotNull(message = "关联计划关联mes_plan表的id不能为空")
private Long planId; private Long planId;
@Schema(description = "来源(新增/生产中)") @Schema(description = "来源(新增/生产中)")

@ -60,4 +60,11 @@ public class RecipeDO extends BaseDO {
*/ */
private String dataUnit; private String dataUnit;
/**
*
*/
private Long machineId;
} }

@ -523,9 +523,16 @@ public class DeviceServiceImpl implements DeviceService {
}else if(Objects.equals(createReqVO.getIsConnect(), DeviceConnectionStatusEnum.DISCONNECTED.getStatus())){ }else if(Objects.equals(createReqVO.getIsConnect(), DeviceConnectionStatusEnum.DISCONNECTED.getStatus())){
boolean disconnect = OpcUtils.disconnect(); boolean disconnect = OpcUtils.disconnect();
if (disconnect){ if (disconnect){
//更新连接状态
deviceDO.setStatus(String.valueOf(DeviceConnectionStatusEnum.DISCONNECTED.getStatus())); deviceDO.setStatus(String.valueOf(DeviceConnectionStatusEnum.DISCONNECTED.getStatus()));
deviceMapper.updateById(deviceDO); deviceMapper.updateById(deviceDO);
//停止定时任务
taskSchedulerManager.stopDeviceTask(deviceDO.getId()); taskSchedulerManager.stopDeviceTask(deviceDO.getId());
//更新运行状态
updateOperationalStatus(deviceDO);
}else { }else {
throw exception(OPC_CLOSE_CONNECT_FAILURE); throw exception(OPC_CLOSE_CONNECT_FAILURE);
} }
@ -536,6 +543,13 @@ public class DeviceServiceImpl implements DeviceService {
return Boolean.TRUE; return Boolean.TRUE;
} }
private void updateOperationalStatus(DeviceDO deviceDO) {
DeviceOperationRecordDO deviceOperationRecordDO = new DeviceOperationRecordDO();
deviceOperationRecordDO.setDeviceId(deviceDO.getId());
deviceOperationRecordDO.setRule(DeviceStatusEnum.OFFLINE.getCode());
deviceOperationRecordMapper.insert(deviceOperationRecordDO);
}
private DeviceDO validateConnectRequest(DeviceSaveReqVO createReqVO) { private DeviceDO validateConnectRequest(DeviceSaveReqVO createReqVO) {
if(createReqVO.getId() == null){ if(createReqVO.getId() == null){
throw exception(DEVICE_ID_DOES_NOT_EXIST); throw exception(DEVICE_ID_DOES_NOT_EXIST);

@ -53,4 +53,6 @@ public interface DeviceContactModelService {
PageResult<DeviceContactModelDO> getDeviceContactModelPage(DeviceContactModelPageReqVO pageReqVO); PageResult<DeviceContactModelDO> getDeviceContactModelPage(DeviceContactModelPageReqVO pageReqVO);
List<DeviceContactModelDO> getDeviceContactModelList(Long id); List<DeviceContactModelDO> getDeviceContactModelList(Long id);
List<DeviceContactModelDO> selectListByDeviceId(Long id);
} }

@ -99,4 +99,9 @@ public class DeviceContactModelServiceImpl implements DeviceContactModelService
.orderByDesc(DeviceContactModelDO::getCreateTime)); .orderByDesc(DeviceContactModelDO::getCreateTime));
} }
@Override
public List<DeviceContactModelDO> selectListByDeviceId(Long id) {
return deviceContactModelMapper.selectList(Wrappers.<DeviceContactModelDO>lambdaQuery().eq(DeviceContactModelDO::getDeviceId,id));
}
} }

@ -3,6 +3,9 @@ package cn.iocoder.yudao.module.iot.service.devicemodelattribute;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO;
import cn.iocoder.yudao.module.erp.service.product.ErpProductUnitService;
import cn.iocoder.yudao.module.iot.dal.dataobject.deviceattributetype.DeviceAttributeTypeDO; import cn.iocoder.yudao.module.iot.dal.dataobject.deviceattributetype.DeviceAttributeTypeDO;
import cn.iocoder.yudao.module.iot.dal.mysql.deviceattributetype.DeviceAttributeTypeMapper; import cn.iocoder.yudao.module.iot.dal.mysql.deviceattributetype.DeviceAttributeTypeMapper;
import cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants; import cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants;
@ -32,6 +35,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.iot.dal.mysql.devicemodelattribute.DeviceModelAttributeMapper; import cn.iocoder.yudao.module.iot.dal.mysql.devicemodelattribute.DeviceModelAttributeMapper;
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.convertSet;
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
/** /**
@ -53,6 +57,9 @@ import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
@Resource @Resource
private DeviceAttributeTypeMapper deviceAttributeTypeMapper; private DeviceAttributeTypeMapper deviceAttributeTypeMapper;
@Resource
private ErpProductUnitService productUnitService;
@Override @Override
public Long createDeviceModelAttribute(DeviceModelAttributeSaveReqVO createReqVO) { public Long createDeviceModelAttribute(DeviceModelAttributeSaveReqVO createReqVO) {
@ -115,9 +122,33 @@ import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
// List<DeviceAttributeTypeDO> attributeTypes = deviceAttributeTypeMapper.selectList(); // List<DeviceAttributeTypeDO> attributeTypes = deviceAttributeTypeMapper.selectList();
// Map<Long, String> typeNameMap = attributeTypes.stream() // Map<Long, String> typeNameMap = attributeTypes.stream()
// .collect(Collectors.toMap(DeviceAttributeTypeDO::getId, DeviceAttributeTypeDO::getName)); // .collect(Collectors.toMap(DeviceAttributeTypeDO::getId, DeviceAttributeTypeDO::getName));
Map<Long, ErpProductUnitDO> unitMap = productUnitService.getProductUnitMap(
pageResult.getList().stream()
.map(DeviceModelAttributeDO::getDataUnit)
.filter(StringUtils::isNotEmpty)
.map(str -> {
try {
return Long.valueOf(str.trim());
} catch (NumberFormatException e) {
return null;
}
})
.filter(Objects::nonNull)
.collect(Collectors.toSet())
);
// 转换并设置类型名称 // 转换并设置类型名称
PageResult<DeviceModelAttributeRespVO> respPageResult = BeanUtils.toBean(pageResult, DeviceModelAttributeRespVO.class); PageResult<DeviceModelAttributeRespVO> respPageResult = BeanUtils.toBean(pageResult, DeviceModelAttributeRespVO.class, deviceModelAttribute -> {
String dataUnitStr = deviceModelAttribute.getDataUnit();
if (StringUtils.isNotBlank(dataUnitStr)) {
try {
Long dataUnitId = Long.valueOf(dataUnitStr.trim());
MapUtils.findAndThen(unitMap, dataUnitId,
unit -> deviceModelAttribute.setDataUnitName(unit.getName()));
} catch (NumberFormatException e) {
}
}
});
// respPageResult.getList().forEach(item -> { // respPageResult.getList().forEach(item -> {
// String typeName = typeNameMap.get(item.getAttributeType()); // String typeName = typeNameMap.get(item.getAttributeType());
@ -252,7 +283,7 @@ import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
importAttributes.forEach(importAttribute -> { importAttributes.forEach(importAttribute -> {
// 4.1 设置设备型号ID // 4.1 设置设备型号ID
importAttribute.setDeviceModelId(deviceModelId); importAttribute.setDeviceModelId(deviceModelId);
// 4.2 处理点位类型转换 // 4.2 处理点位类型转换
String typeName = importAttribute.getTypeName(); String typeName = importAttribute.getTypeName();
if (StringUtils.isBlank(typeName)) { if (StringUtils.isBlank(typeName)) {

@ -52,4 +52,7 @@ public interface RecipeDeviceRecordService {
*/ */
PageResult<RecipeDeviceRecordDO> getRecipeDeviceRecordPage(RecipeDeviceRecordPageReqVO pageReqVO); PageResult<RecipeDeviceRecordDO> getRecipeDeviceRecordPage(RecipeDeviceRecordPageReqVO pageReqVO);
List<RecipeDeviceRecordDO> getListByRecipeId(Long recipeId);
void deleteByIds(List<RecipeDeviceRecordDO> recipeDeviceRecordDOS);
} }

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.iot.service.recipedevicerecord; package cn.iocoder.yudao.module.iot.service.recipedevicerecord;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -31,6 +32,7 @@ public class RecipeDeviceRecordServiceImpl implements RecipeDeviceRecordService
@Override @Override
public Long createRecipeDeviceRecord(RecipeDeviceRecordSaveReqVO createReqVO) { public Long createRecipeDeviceRecord(RecipeDeviceRecordSaveReqVO createReqVO) {
// 插入 // 插入
RecipeDeviceRecordDO recipeDeviceRecord = BeanUtils.toBean(createReqVO, RecipeDeviceRecordDO.class); RecipeDeviceRecordDO recipeDeviceRecord = BeanUtils.toBean(createReqVO, RecipeDeviceRecordDO.class);
recipeDeviceRecordMapper.insert(recipeDeviceRecord); recipeDeviceRecordMapper.insert(recipeDeviceRecord);
@ -71,4 +73,16 @@ public class RecipeDeviceRecordServiceImpl implements RecipeDeviceRecordService
return recipeDeviceRecordMapper.selectPage(pageReqVO); return recipeDeviceRecordMapper.selectPage(pageReqVO);
} }
@Override
public List<RecipeDeviceRecordDO> getListByRecipeId(Long recipeId) {
return recipeDeviceRecordMapper.selectList(Wrappers.<RecipeDeviceRecordDO>lambdaQuery().eq(RecipeDeviceRecordDO::getRecipeId, recipeId));
}
@Override
public void deleteByIds(List<RecipeDeviceRecordDO> recipeDeviceRecordDOS) {
recipeDeviceRecordMapper.deleteByIds(recipeDeviceRecordDOS);
}
} }

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.iot.service.recipepointrecord; package cn.iocoder.yudao.module.iot.service.recipepointrecord;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -31,6 +32,12 @@ public class RecipePointRecordServiceImpl implements RecipePointRecordService {
@Override @Override
public Long createRecipePointRecord(RecipePointRecordSaveReqVO createReqVO) { public Long createRecipePointRecord(RecipePointRecordSaveReqVO createReqVO) {
List<RecipePointRecordDO> recipePointRecordDOS = recipePointRecordMapper.selectList(Wrappers.<RecipePointRecordDO>lambdaQuery().eq(RecipePointRecordDO::getRecipeId, createReqVO.getRecipeId()));
if (!recipePointRecordDOS.isEmpty()){
recipePointRecordMapper.deleteByIds(recipePointRecordDOS);
}
// 插入 // 插入
RecipePointRecordDO recipePointRecord = BeanUtils.toBean(createReqVO, RecipePointRecordDO.class); RecipePointRecordDO recipePointRecord = BeanUtils.toBean(createReqVO, RecipePointRecordDO.class);
recipePointRecordMapper.insert(recipePointRecord); recipePointRecordMapper.insert(recipePointRecord);

@ -143,6 +143,8 @@ public interface ErrorCodeConstants {
ErrorCode SUBJECT_EXISTS = new ErrorCode(1002000010, "项目编码已存在"); ErrorCode SUBJECT_EXISTS = new ErrorCode(1002000010, "项目编码已存在");
ErrorCode TASK_MANAGEMENT_NOT_EXISTS = new ErrorCode(1002000011, "设备类型不存在"); ErrorCode TASK_MANAGEMENT_NOT_EXISTS = new ErrorCode(1002000011, "设备类型不存在");
ErrorCode TASK_CORN_NOT_EXISTS = new ErrorCode(1002000011, "设备corn表达式为空"); ErrorCode TASK_CORN_NOT_EXISTS = new ErrorCode(1002000011, "设备corn表达式为空");
ErrorCode TASK_CORN_NOT_LE_HOUR = new ErrorCode(1002000011, "corn表达式不能小于一小时");
ErrorCode TICKET_MANAGEMENT_NOT_EXISTS = new ErrorCode(1002000012, "工单管理不存在"); ErrorCode TICKET_MANAGEMENT_NOT_EXISTS = new ErrorCode(1002000012, "工单管理不存在");
ErrorCode TICKET_RESULTS_NOT_EXISTS = new ErrorCode(1002000013, "工单检验结果不存在"); ErrorCode TICKET_RESULTS_NOT_EXISTS = new ErrorCode(1002000013, "工单检验结果不存在");
ErrorCode TICKET_RESULTS_ID_NOT_NULL = new ErrorCode(1002000014, "工单检验结果Id不存在"); ErrorCode TICKET_RESULTS_ID_NOT_NULL = new ErrorCode(1002000014, "工单检验结果Id不存在");

@ -16,6 +16,11 @@ import cn.iocoder.yudao.module.mes.dal.mysql.ticketmanagement.TicketManagementMa
import cn.iocoder.yudao.module.mes.dal.mysql.ticketresults.TicketResultsMapper; import cn.iocoder.yudao.module.mes.dal.mysql.ticketresults.TicketResultsMapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cronutils.model.Cron;
import com.cronutils.model.CronType;
import com.cronutils.model.definition.CronDefinitionBuilder;
import com.cronutils.model.time.ExecutionTime;
import com.cronutils.parser.CronParser;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
@ -23,6 +28,8 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.ZonedDateTime;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -73,6 +80,12 @@ public class TaskManagementServiceImpl implements TaskManagementService {
@Override @Override
public Long createTaskManagement(TaskManagementSaveReqVO createReqVO) { public Long createTaskManagement(TaskManagementSaveReqVO createReqVO) {
String cronExpr = createReqVO.getCronExpression();
// 校验 cron 表达式最小间隔
isCronIntervalAtLeastOneHour(cronExpr);
// 插入 // 插入
TaskManagementDO taskManagement = BeanUtils.toBean(createReqVO, TaskManagementDO.class); TaskManagementDO taskManagement = BeanUtils.toBean(createReqVO, TaskManagementDO.class);
taskManagementMapper.insert(taskManagement); taskManagementMapper.insert(taskManagement);
@ -80,6 +93,35 @@ public class TaskManagementServiceImpl implements TaskManagementService {
return taskManagement.getId(); return taskManagement.getId();
} }
private void isCronIntervalAtLeastOneHour(String cronExpr) {
try {
if (StringUtils.isBlank(cronExpr)){
return;
}
CronParser parser = new CronParser(CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ));
Cron cron = parser.parse(cronExpr);
cron.validate();
ExecutionTime executionTime = ExecutionTime.forCron(cron);
ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime next1 = executionTime.nextExecution(now).get();
ZonedDateTime next2 = executionTime.nextExecution(next1).get();
Duration duration = Duration.between(next1, next2);
if (duration.toHours() < 1) {
throw exception(TASK_CORN_NOT_LE_HOUR);
}
} catch (Exception e) {
throw exception(TASK_CORN_NOT_LE_HOUR);
}
}
@Override @Override
public void updateTaskManagement(TaskManagementSaveReqVO updateReqVO) { public void updateTaskManagement(TaskManagementSaveReqVO updateReqVO) {
// 校验存在 // 校验存在

Loading…
Cancel
Save