fix: 完善清扫记录;增加告警推送

master
wangrunpu 3 weeks ago
parent b39d89ba88
commit f2676dec9d

@ -40,4 +40,7 @@ public class IotAlertRecordRespVO {
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime updateTime;
}

@ -62,4 +62,5 @@ public interface IotAlertRecordService {
*/
Long createAlertRecord(IotAlertConfigDO config, Long sceneRuleId, IotDeviceMessage deviceMessage);
Long createAlertRecord(IotAlertRecordDO alertRecordDO);
}

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.iot.service.alert;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.iot.controller.admin.alert.vo.recrod.IotAlertRecordPageReqVO;
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
@ -8,19 +9,26 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.alert.IotAlertConfigDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.alert.IotAlertRecordDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
import cn.iocoder.yudao.module.iot.dal.mysql.alert.IotAlertRecordMapper;
import cn.iocoder.yudao.module.iot.framework.job.core.IotSchedulerManager;
import cn.iocoder.yudao.module.iot.framework.mqtt.config.ProvincialPlatformMqttProperties;
import cn.iocoder.yudao.module.iot.job.alert.IotAlertRecordPushJob;
import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.quartz.SchedulerException;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* IoT Service
*
* @author
*/
@Slf4j
@Service
@Validated
public class IotAlertRecordServiceImpl implements IotAlertRecordService {
@ -31,6 +39,12 @@ public class IotAlertRecordServiceImpl implements IotAlertRecordService {
@Resource
private IotDeviceService deviceService;
@Resource(name = "iotSchedulerManager")
private IotSchedulerManager schedulerManager;
@Resource(required = false)
private ProvincialPlatformMqttProperties mqttProperties;
@Override
public IotAlertRecordDO getAlertRecord(Long id) {
return alertRecordMapper.selectById(id);
@ -54,6 +68,11 @@ public class IotAlertRecordServiceImpl implements IotAlertRecordService {
// 批量更新告警记录的处理状态
alertRecordMapper.updateList(ids, IotAlertRecordDO.builder()
.processStatus(true).processRemark(processRemark).build());
// 停止所有相关告警的推送定时任务
for (Long alertRecordId : ids) {
stopAlertPushJob(alertRecordId);
}
}
@Override
@ -77,4 +96,79 @@ public class IotAlertRecordServiceImpl implements IotAlertRecordService {
return record.getId();
}
@Override
public Long createAlertRecord(IotAlertRecordDO alertRecordDO) {
alertRecordMapper.insert(alertRecordDO);
// 启动定时任务推送告警记录到省平台
startAlertPushJob(alertRecordDO.getId());
return alertRecordDO.getId();
}
/**
*
*
* @param alertRecordId
*/
private void startAlertPushJob(Long alertRecordId) {
// 检查是否启用省平台MQTT推送
if (mqttProperties == null || !Boolean.TRUE.equals(mqttProperties.getEnabled())) {
log.debug("[startAlertPushJob][省平台MQTT推送未启用跳过启动定时任务告警ID: {}]", alertRecordId);
return;
}
try {
// 构建任务名称和数据
String jobName = buildAlertPushJobName(alertRecordId);
Map<String, Object> jobDataMap = MapUtil.of(IotAlertRecordPushJob.JOB_DATA_KEY_ALERT_RECORD_ID, alertRecordId);
// 构建CRON表达式每N秒执行一次从配置中读取
Integer pushIntervalSeconds = mqttProperties.getPushIntervalSeconds();
String cronExpression = String.format("0/%d * * * * ?", pushIntervalSeconds);
// 注册定时任务
schedulerManager.addOrUpdateJob(
IotAlertRecordPushJob.class,
jobName,
cronExpression,
jobDataMap
);
log.info("[startAlertPushJob][启动告警推送定时任务成功告警ID: {}, 推送间隔: {}秒]",
alertRecordId, pushIntervalSeconds);
} catch (SchedulerException e) {
log.error("[startAlertPushJob][启动告警推送定时任务失败告警ID: {}]", alertRecordId, e);
}
}
/**
*
*
* @param alertRecordId
*/
private void stopAlertPushJob(Long alertRecordId) {
// 检查是否启用省平台MQTT推送
if (mqttProperties == null || !Boolean.TRUE.equals(mqttProperties.getEnabled())) {
return;
}
try {
String jobName = buildAlertPushJobName(alertRecordId);
schedulerManager.deleteJob(jobName);
log.info("[stopAlertPushJob][停止告警推送定时任务成功告警ID: {}]", alertRecordId);
} catch (SchedulerException e) {
log.error("[stopAlertPushJob][停止告警推送定时任务失败告警ID: {}]", alertRecordId, e);
}
}
/**
*
*
* @param alertRecordId
* @return
*/
private String buildAlertPushJobName(Long alertRecordId) {
return String.format("%s_%d", IotAlertRecordPushJob.class.getSimpleName(), alertRecordId);
}
}

@ -17,9 +17,11 @@ import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum;
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer;
import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils;
import cn.iocoder.yudao.module.iot.dal.dataobject.alert.IotAlertRecordDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceMessageDO;
import cn.iocoder.yudao.module.iot.dal.tdengine.IotDeviceMessageMapper;
import cn.iocoder.yudao.module.iot.service.alert.IotAlertRecordService;
import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
import cn.iocoder.yudao.module.iot.service.device.property.IotDevicePropertyService;
import cn.iocoder.yudao.module.iot.service.ota.IotOtaTaskRecordService;
@ -35,6 +37,7 @@ import org.springframework.validation.annotation.Validated;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -52,6 +55,8 @@ import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DEVICE_DOWNST
@Slf4j
public class IotDeviceMessageServiceImpl implements IotDeviceMessageService {
@Resource
private IotAlertRecordService alertRecordService;
@Resource
private IotDeviceService deviceService;
@Resource
@ -203,6 +208,22 @@ public class IotDeviceMessageServiceImpl implements IotDeviceMessageService {
return null;
}
// 事件上报 TODO 以后事件触发器完善后 需要剔除这里的处理
if (Objects.equal(message.getMethod(), IotDeviceMessageMethodEnum.EVENT_POST.getMethod())) {
HashMap<String, Object> params = (HashMap<String, Object>) message.getParams();
IotAlertRecordDO alertRecordDO = new IotAlertRecordDO();
alertRecordDO.setConfigId(0L);
alertRecordDO.setConfigName("温度高报");
alertRecordDO.setConfigLevel(3);
alertRecordDO.setSceneRuleId(0L);
alertRecordDO.setDeviceId(device.getId());
alertRecordDO.setProductId(device.getProductId());
alertRecordDO.setDeviceMessage(message);
alertRecordService.createAlertRecord(alertRecordDO);
return null;
}
// OTA 上报升级进度
if (Objects.equal(message.getMethod(), IotDeviceMessageMethodEnum.OTA_PROGRESS.getMethod())) {
otaTaskRecordService.updateOtaRecordProgress(device, message);

@ -1,5 +1,8 @@
package cn.iocoder.yudao.module.system.controller.admin.dustclearrecord;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
@ -42,6 +45,10 @@ public class DustClearrecordController {
@Operation(summary = "创建粉尘清扫打卡记录")
@PreAuthorize("@ss.hasPermission('system:dust-clearrecord:create')")
public CommonResult<String> createDustClearrecord(@Valid @RequestBody DustClearrecordSaveReqVO createReqVO) {
List<String> clearItemNameList = createReqVO.getClearItemNameList();
if (CollUtil.isNotEmpty(clearItemNameList)) {
createReqVO.setClearItemName(String.join(",", clearItemNameList));
}
return success(dustClearrecordService.createDustClearrecord(createReqVO));
}
@ -49,6 +56,10 @@ public class DustClearrecordController {
@Operation(summary = "更新粉尘清扫打卡记录")
@PreAuthorize("@ss.hasPermission('system:dust-clearrecord:update')")
public CommonResult<Boolean> updateDustClearrecord(@Valid @RequestBody DustClearrecordSaveReqVO updateReqVO) {
List<String> clearItemNameList = updateReqVO.getClearItemNameList();
if (CollUtil.isNotEmpty(clearItemNameList)) {
updateReqVO.setClearItemName(String.join(",", clearItemNameList));
}
dustClearrecordService.updateDustClearrecord(updateReqVO);
return success(true);
}
@ -77,6 +88,10 @@ public class DustClearrecordController {
@PreAuthorize("@ss.hasPermission('system:dust-clearrecord:query')")
public CommonResult<DustClearrecordRespVO> getDustClearrecord(@RequestParam("id") String id) {
DustClearrecordDO dustClearrecord = dustClearrecordService.getDustClearrecord(id);
String clearItemName = dustClearrecord.getClearItemName();
if (StringUtils.isNotEmpty(clearItemName)) {
dustClearrecord.setClearItemNameList(Arrays.asList(clearItemName.split(",")));
}
return success(BeanUtils.toBean(dustClearrecord, DustClearrecordRespVO.class));
}
@ -85,6 +100,13 @@ public class DustClearrecordController {
@PreAuthorize("@ss.hasPermission('system:dust-clearrecord:query')")
public CommonResult<PageResult<DustClearrecordRespVO>> getDustClearrecordPage(@Valid DustClearrecordPageReqVO pageReqVO) {
PageResult<DustClearrecordDO> pageResult = dustClearrecordService.getDustClearrecordPage(pageReqVO);
List<DustClearrecordDO> list = pageResult.getList();
list.forEach(item -> {
String clearItemName = item.getClearItemName();
if (StringUtils.isNotEmpty(clearItemName)) {
item.setClearItemNameList(Arrays.asList(clearItemName.split(",")));
}
});
return success(BeanUtils.toBean(pageResult, DustClearrecordRespVO.class));
}

@ -23,6 +23,7 @@ public class DustClearrecordRespVO {
@Schema(description = "清扫项目", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
@ExcelProperty("清扫项目")
private String clearItemName;
private List<String> clearItemNameList;
@Schema(description = "完成情况 0:未完成;1:已完成", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("完成情况 0:未完成;1:已完成")

@ -19,9 +19,11 @@ public class DustClearrecordSaveReqVO {
private String dataId;
@Schema(description = "清扫项目", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
@NotEmpty(message = "清扫项目不能为空")
private String clearItemName;
@NotEmpty(message = "清扫项目不能为空")
private List<String> clearItemNameList;
@Schema(description = "完成情况 0:未完成;1:已完成", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "完成情况 0:未完成;1:已完成不能为空")
private String taskProcess;

@ -26,7 +26,7 @@ public class DustClearrecordDO extends BaseDO {
/**
*
*/
@TableId(type = IdType.INPUT)
@TableId(type = IdType.ASSIGN_ID)
private String id;
/**
*
@ -36,6 +36,8 @@ public class DustClearrecordDO extends BaseDO {
*
*/
private String clearItemName;
@TableField(exist = false)
private List<String> clearItemNameList;
/**
* 0:;1:
*/

@ -81,6 +81,9 @@ public class AdminAuthServiceImpl implements AdminAuthService {
@Override
public AdminUserDO authenticate(String username, String password) {
final LoginLogTypeEnum logTypeEnum = LoginLogTypeEnum.LOGIN_USERNAME;
// 临时忽略租户隔离,因为登录时还不知道用户属于哪个租户
TenantContextHolder.setIgnore(true);
try {
// 校验账号是否存在
AdminUserDO user = userService.getUserByUsername(username);
if (user == null) {
@ -96,7 +99,13 @@ public class AdminAuthServiceImpl implements AdminAuthService {
createLoginLog(user.getId(), username, logTypeEnum, LoginResultEnum.USER_DISABLED);
throw exception(AUTH_LOGIN_USER_DISABLED);
}
// 设置用户所属租户到上下文
TenantContextHolder.setTenantId(user.getTenantId());
return user;
} finally {
// 恢复租户隔离
TenantContextHolder.setIgnore(false);
}
}
@Override
@ -113,7 +122,6 @@ public class AdminAuthServiceImpl implements AdminAuthService {
socialUserService.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(),
reqVO.getSocialType(), reqVO.getSocialCode(), reqVO.getSocialState()));
}
if (ObjectUtil.isNull(TenantContextHolder.getTenantId())) TenantContextHolder.setTenantId(user.getTenantId());
// 创建 Token 令牌,记录登录日志
return createTokenAfterLoginSuccess(user.getId(), reqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME);
}
@ -141,14 +149,24 @@ public class AdminAuthServiceImpl implements AdminAuthService {
// 校验验证码
smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.ADMIN_MEMBER_LOGIN.getScene(), getClientIP())).checkError();
// 临时忽略租户隔离,因为登录时还不知道用户属于哪个租户
TenantContextHolder.setIgnore(true);
try {
// 获得用户信息
AdminUserDO user = userService.getUserByUsername(reqVO.getMobile());
if (user == null) {
throw exception(USER_NOT_EXISTS);
}
// 设置用户所属租户到上下文
TenantContextHolder.setTenantId(user.getTenantId());
// 创建 Token 令牌,记录登录日志
return createTokenAfterLoginSuccess(user.getId(), reqVO.getMobile(), LoginLogTypeEnum.LOGIN_MOBILE);
} finally {
// 恢复租户隔离
TenantContextHolder.setIgnore(false);
}
}
private void createLoginLog(Long userId, String username,

Loading…
Cancel
Save