设备控制完善日志,以及更新用户获取工具

master
lld 2026-01-30 02:12:44 +08:00
parent f8f37ae22b
commit c7d19dd442
8 changed files with 68 additions and 18 deletions

View File

@ -43,7 +43,7 @@ server:
# 日志配置
logging:
level:
com.agri: debug
com.agri: info
org.springframework: warn
# 用户配置

View File

@ -5,6 +5,8 @@ import com.agri.common.constant.HttpStatus;
import com.agri.common.core.domain.entity.SysRole;
import com.agri.common.core.domain.model.LoginUser;
import com.agri.common.exception.ServiceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@ -22,6 +24,8 @@ import java.util.stream.Collectors;
public class SecurityUtils
{
private static final Logger log = LoggerFactory.getLogger(SecurityUtils.class);
/**
* ID
**/
@ -72,14 +76,16 @@ public class SecurityUtils
**/
public static LoginUser getLoginUser()
{
LoginUser loginUser = null;
try
{
return (LoginUser) getAuthentication().getPrincipal();
loginUser = (LoginUser) getAuthentication().getPrincipal();
}
catch (Exception e)
{
throw new ServiceException("获取用户信息异常", HttpStatus.UNAUTHORIZED);
log.error("获取用户信息异常: {}", HttpStatus.UNAUTHORIZED);
}
return loginUser;
}
/**

View File

@ -31,7 +31,7 @@ public class MybatisPlusHandler implements MetaObjectHandler {
// 填充创建时间字段名createTime当前时间
this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
// 示例填充创建人假设从上下文获取当前用户ID
this.strictInsertFill(metaObject, "createBy", String.class, getLoginUser().getUsername());
this.strictInsertFill(metaObject, "createBy", String.class, getLoginUser()!=null?getLoginUser().getUsername():"");
}
// 更新操作时自动填充
@ -40,6 +40,6 @@ public class MybatisPlusHandler implements MetaObjectHandler {
// 填充更新时间字段名updateTime当前时间
this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
// 示例:填充更新人
this.strictUpdateFill(metaObject, "updateBy", String.class, getLoginUser().getUsername());
this.strictUpdateFill(metaObject, "updateBy", String.class, getLoginUser()!=null?getLoginUser().getUsername():"");
}
}

View File

@ -190,6 +190,7 @@ public class DeviceStatusHandler {
.set(SysDevOperLog::getAckReceived,1)
.set(SysDevOperLog::getIsLockSuc,1)
.set(SysDevOperLog::getAckSuc, 1)
.set(SysDevOperLog::getUpdateBy,"自动关")
.set(SysDevOperLog::getIsTask,autoOffSeconds > 0?1:0)
.set(ObjectUtils.isEmpty(autoOffSeconds), SysDevOperLog::getNoTaskReason,"当前运行时间:【"+autoOffSeconds+"】")
.set(SysDevOperLog::getAck, payload)
@ -289,7 +290,7 @@ public class DeviceStatusHandler {
}
} catch (MqttException e) {
WxUtil.pushText(
"【消息转发失败】\n deviceId: "+deviceId+"\n payload: "+payload+"\n msg: "+e.getMessage()+"\n cause: "+e.getCause());
"【消息转发失败】\n deviceId: "+deviceId+"\n payload: "+payload+"\n cause: "+e);
log.error("【消息转发失败】deviceId={}, msg={}", deviceId, e.getMessage(), e);
}
}

View File

@ -9,6 +9,7 @@ import com.agri.system.service.ISysAgriInfoService;
import com.agri.system.service.ISysAgriLimitService;
import com.agri.system.service.ISysDevOperLogService;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import org.apache.commons.lang3.ObjectUtils;
import org.eclipse.paho.client.mqttv3.MqttException;
@ -67,7 +68,7 @@ public class FrontendControlHandler {
private ISysDevOperLogService sysDevOperLogService;
@Value("${dtu-ctl-lock-ttl}")
@Value("${spring.mqtt.dtu-ctl-lock-ttl}")
private int dtuCtlLockTTL;
private static final Map<String, Function<SysAgriLimit, Integer>> LIMIT_MAP = new HashMap<>();
static {
@ -94,7 +95,20 @@ public class FrontendControlHandler {
log.error("【指令处理】clientId或deviceId为空topic={}", topic);
return;
}
// 4. 转发指令到设备
String deviceTopic = "dtu/" + deviceId + "/down";
JSONObject payloadObj;
try {
payloadObj = JSON.parseObject(payload);
} catch (Exception e) {
log.error("【设备处理】JSON解析失败payload={}", payload, e);
return;
}
if (payloadObj.containsKey("read")) {
mqttMessageSender.publish(deviceTopic, payload);
log.info("【主动读取】设备{}主动读取payload={}",deviceId, payload);
return;
}
// 解析功能码({"功能码":状态码}格式)
Map<String, Integer> funcCodeMap = null;
try {
@ -139,11 +153,9 @@ public class FrontendControlHandler {
log.info("【指令处理】前端{}于{}控制设备{}的{}功能,指令:{}",
clientId, LocalDateTime.now(), deviceId, funcType, payload);
// 4. 转发指令到设备
String deviceTopic = "dtu/" + deviceId + "/down";
//todo
mqttMessageSender.publish(deviceTopic, payload);
// testAutoOffTask(deviceId,funcCodeMap);
SysAgriInfo agriInfo = sysAgriInfoService.lambdaQuery()
.eq(SysAgriInfo::getImei, deviceId)
@ -159,7 +171,11 @@ public class FrontendControlHandler {
logDto.setLockAcquired(1);
logDto.setLockHolder(clientId);
logDto.setExecResult(1);
sysDevOperLogService.save(logDto);
logDto.setCreateBy("手动控制");
boolean save = sysDevOperLogService.save(logDto);
// if (save) {
// testAutoOffTask(deviceId,funcCodeMap);
// }
log.info("【指令转发】前端{} → 设备{}的{}功能", clientId, deviceId, funcType);
}
@ -169,7 +185,10 @@ public class FrontendControlHandler {
Integer funcValue = funcCodeMap.get(funcType);
// 释放对应功能的分布式锁
String lockKey = "lock:" + deviceId + ":" + funcType;
stringRedisTemplate.delete(lockKey);
Boolean delete = stringRedisTemplate.delete(lockKey);
if (delete) {
log.info("【设备控制锁删除成功!】");
}
// 回执成功且值=1时启动自动关闭任务保留原有逻辑
if (StringUtils.hasText(funcType) && funcValue != null && funcValue == 1) {
@ -184,9 +203,27 @@ public class FrontendControlHandler {
if (autoOffSeconds > 0) {
mqttAutoOffManager.scheduleAutoOff(deviceId, funcType, autoOffSeconds);
log.debug("【自动关任务】标记需要执行deviceId={}, funcType={}, delay={}s", deviceId, funcType, autoOffSeconds);
} else {
log.debug("【自动关任务】标记不符合执行运行时间未配置deviceId={}, funcType={}, delay={}s", deviceId, funcType, autoOffSeconds);
}
sysDevOperLogService.lambdaUpdate()
.eq(SysDevOperLog::getImei, deviceId)
.eq(SysDevOperLog::getFuncCode, funcType)
.eq(SysDevOperLog::getOpType, funcValue)
.eq(SysDevOperLog::getLockAcquired,1)
.orderByDesc(SysDevOperLog::getCreateTime)
.last("LIMIT 1")
.set(SysDevOperLog::getAckReceived,1)
.set(SysDevOperLog::getIsLockSuc,1)
.set(SysDevOperLog::getAckSuc, 1)
.set(SysDevOperLog::getIsTask, 1)
.set(SysDevOperLog::getUpdateBy,"自动关")
.set(autoOffSeconds <= 0, SysDevOperLog::getNoTaskReason,"当前运行时间:【"+autoOffSeconds+"】")
.set(SysDevOperLog::getUpdateBy, "测试")
.set(SysDevOperLog::getExecResult, 1)
.update();
}
if (StringUtils.hasText(funcType) && funcValue != null && funcValue == 0) {

View File

@ -70,7 +70,7 @@ public class MqttAutoOffManager {
@Value("${spring.mqtt.auto-off-thread-pool-size:5}")
private int autoOffThreadPoolSize;
@Value("${dtu-ctl-lock-ttl}")
@Value("${spring.mqtt.dtu-ctl-lock-ttl}")
private int dtuCtlLockTTL;
@Autowired
@ -191,7 +191,7 @@ public class MqttAutoOffManager {
try {
runAutoOff(deviceId, funcType);
} catch (Exception e) {
WxUtil.pushText("【自动关任务】提交任务失败! \n deviceId: "+deviceId+"\n funcType: "+funcType+"\n msg: "+e.getMessage()+"\n cause: "+e.getCause());
WxUtil.pushText("【自动关任务】提交任务失败! \n deviceId: "+deviceId+"\n funcType: "+funcType+"\n cause: "+e);
log.error("【自动关任务】执行失败deviceId={}, funcType={}", deviceId, funcType, e);
} finally {
// 任务执行完成后移除映射
@ -226,7 +226,7 @@ public class MqttAutoOffManager {
latestObj = JSON.parseObject(latest);
} catch (Exception e) {
skipReason = "【自动关任务】执行报错-解析异常";
WxUtil.pushText("自动关任务执行报错-解析异常:\n deviceId: " + deviceId + "\n funcType:" + funcType+"\n 异常:"+e.getMessage()+"\n Cause: "+e.getCause());
WxUtil.pushText("自动关任务执行报错-解析异常:\n deviceId: " + deviceId + "\n funcType:" + funcType+"\n Cause: "+e);
log.warn("【自动关任务】最新状态JSON解析失败跳过deviceId={}, funcType={}", deviceId, funcType);
return;
}
@ -244,7 +244,9 @@ public class MqttAutoOffManager {
} catch (Exception ignore) {
skipReason = "【自动关任务】最新状态功能码获取失败";
}
if (current == null || current!=1) {
skipReason = "【自动关任务】检测未运行或状态未知";
}
sysDevOperLogService.lambdaUpdate()
.eq(SysDevOperLog::getImei, deviceId)
.eq(SysDevOperLog::getFuncCode, funcType)
@ -256,6 +258,7 @@ public class MqttAutoOffManager {
.last("LIMIT 1")
.set(SysDevOperLog::getExecResult,1)
.set(SysDevOperLog::getLatestState, latest)
.set(SysDevOperLog::getUpdateBy,"自动关")
.set(!skipReason.isEmpty(), SysDevOperLog::getSkipReason, skipReason)
.update();
@ -289,6 +292,7 @@ public class MqttAutoOffManager {
logDto.setLockHolder("autoOff");
logDto.setExecResult(1);
logDto.setLatestState(latest);
logDto.setCreateBy("自动关");
logDto.setTaskStatus(getFutureStatus().toString());
sysDevOperLogService.save(logDto);
log.info("【自动关任务】检测仍在运行已下发关闭deviceId={}, funcType={}, payload={}", deviceId, funcType, down.toJSONString());

View File

@ -142,7 +142,7 @@ public class MqttClientManager implements SmartLifecycle {
log.error("【MQTT连接异常】连接断开clientId{},原因:{}",
safeClientId(), (cause == null ? "unknown" : cause.getMessage()), cause);
WxUtil.pushText("【MQTT连接异常】连接断开\n clientId"+safeClientId()+"\n 原因:"+(cause == null ? "unknown" : cause.getMessage())+"\n Cause: "+cause.getCause());
WxUtil.pushText("【MQTT连接异常】连接断开\n clientId"+safeClientId()+"\n Cause: "+cause);
// 【方案A】不再触发自写重连Paho自动重连会接管重连过程
// 这里只记录日志即可
if (isRunning.get()) {

View File

@ -1,5 +1,6 @@
package com.agri.framework.web.dispatcher;
import com.agri.common.utils.wechat.WxUtil;
import com.agri.framework.interceptor.DeviceStatusHandler;
import com.agri.framework.interceptor.FrontendControlHandler;
import com.agri.framework.interceptor.FrontendOnlineHandler;
@ -64,6 +65,7 @@ public class MqttMessageDispatcher {
}
// todo 是否加回复主题??
} catch (Exception e) {
WxUtil.pushText("【MQTT消息处理异常】\n topic: "+ topic+"\n cause: "+e);
log.error("【MQTT消息处理异常】topic={}", topic, e);
}
}