设备控制完善日志,以及更新用户获取工具
parent
f8f37ae22b
commit
c7d19dd442
|
|
@ -43,7 +43,7 @@ server:
|
||||||
# 日志配置
|
# 日志配置
|
||||||
logging:
|
logging:
|
||||||
level:
|
level:
|
||||||
com.agri: debug
|
com.agri: info
|
||||||
org.springframework: warn
|
org.springframework: warn
|
||||||
|
|
||||||
# 用户配置
|
# 用户配置
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ import com.agri.common.constant.HttpStatus;
|
||||||
import com.agri.common.core.domain.entity.SysRole;
|
import com.agri.common.core.domain.entity.SysRole;
|
||||||
import com.agri.common.core.domain.model.LoginUser;
|
import com.agri.common.core.domain.model.LoginUser;
|
||||||
import com.agri.common.exception.ServiceException;
|
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.Authentication;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
|
@ -22,6 +24,8 @@ import java.util.stream.Collectors;
|
||||||
public class SecurityUtils
|
public class SecurityUtils
|
||||||
{
|
{
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SecurityUtils.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户ID
|
* 用户ID
|
||||||
**/
|
**/
|
||||||
|
|
@ -72,14 +76,16 @@ public class SecurityUtils
|
||||||
**/
|
**/
|
||||||
public static LoginUser getLoginUser()
|
public static LoginUser getLoginUser()
|
||||||
{
|
{
|
||||||
|
LoginUser loginUser = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return (LoginUser) getAuthentication().getPrincipal();
|
loginUser = (LoginUser) getAuthentication().getPrincipal();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
throw new ServiceException("获取用户信息异常", HttpStatus.UNAUTHORIZED);
|
log.error("获取用户信息异常: {}", HttpStatus.UNAUTHORIZED);
|
||||||
}
|
}
|
||||||
|
return loginUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ public class MybatisPlusHandler implements MetaObjectHandler {
|
||||||
// 填充创建时间(字段名:createTime,值:当前时间)
|
// 填充创建时间(字段名:createTime,值:当前时间)
|
||||||
this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
|
this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
|
||||||
// 示例:填充创建人(假设从上下文获取当前用户ID)
|
// 示例:填充创建人(假设从上下文获取当前用户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,值:当前时间)
|
// 填充更新时间(字段名:updateTime,值:当前时间)
|
||||||
this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
|
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():"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -190,6 +190,7 @@ public class DeviceStatusHandler {
|
||||||
.set(SysDevOperLog::getAckReceived,1)
|
.set(SysDevOperLog::getAckReceived,1)
|
||||||
.set(SysDevOperLog::getIsLockSuc,1)
|
.set(SysDevOperLog::getIsLockSuc,1)
|
||||||
.set(SysDevOperLog::getAckSuc, 1)
|
.set(SysDevOperLog::getAckSuc, 1)
|
||||||
|
.set(SysDevOperLog::getUpdateBy,"自动关")
|
||||||
.set(SysDevOperLog::getIsTask,autoOffSeconds > 0?1:0)
|
.set(SysDevOperLog::getIsTask,autoOffSeconds > 0?1:0)
|
||||||
.set(ObjectUtils.isEmpty(autoOffSeconds), SysDevOperLog::getNoTaskReason,"当前运行时间:【"+autoOffSeconds+"】")
|
.set(ObjectUtils.isEmpty(autoOffSeconds), SysDevOperLog::getNoTaskReason,"当前运行时间:【"+autoOffSeconds+"】")
|
||||||
.set(SysDevOperLog::getAck, payload)
|
.set(SysDevOperLog::getAck, payload)
|
||||||
|
|
@ -289,7 +290,7 @@ public class DeviceStatusHandler {
|
||||||
}
|
}
|
||||||
} catch (MqttException e) {
|
} catch (MqttException e) {
|
||||||
WxUtil.pushText(
|
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);
|
log.error("【消息转发失败】deviceId={}, msg={}", deviceId, e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import com.agri.system.service.ISysAgriInfoService;
|
||||||
import com.agri.system.service.ISysAgriLimitService;
|
import com.agri.system.service.ISysAgriLimitService;
|
||||||
import com.agri.system.service.ISysDevOperLogService;
|
import com.agri.system.service.ISysDevOperLogService;
|
||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.alibaba.fastjson2.TypeReference;
|
import com.alibaba.fastjson2.TypeReference;
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||||
|
|
@ -67,7 +68,7 @@ public class FrontendControlHandler {
|
||||||
private ISysDevOperLogService sysDevOperLogService;
|
private ISysDevOperLogService sysDevOperLogService;
|
||||||
|
|
||||||
|
|
||||||
@Value("${dtu-ctl-lock-ttl}")
|
@Value("${spring.mqtt.dtu-ctl-lock-ttl}")
|
||||||
private int dtuCtlLockTTL;
|
private int dtuCtlLockTTL;
|
||||||
private static final Map<String, Function<SysAgriLimit, Integer>> LIMIT_MAP = new HashMap<>();
|
private static final Map<String, Function<SysAgriLimit, Integer>> LIMIT_MAP = new HashMap<>();
|
||||||
static {
|
static {
|
||||||
|
|
@ -94,7 +95,20 @@ public class FrontendControlHandler {
|
||||||
log.error("【指令处理】clientId或deviceId为空,topic={}", topic);
|
log.error("【指令处理】clientId或deviceId为空,topic={}", topic);
|
||||||
return;
|
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;
|
Map<String, Integer> funcCodeMap = null;
|
||||||
try {
|
try {
|
||||||
|
|
@ -139,11 +153,9 @@ public class FrontendControlHandler {
|
||||||
log.info("【指令处理】前端{}于{}控制设备{}的{}功能,指令:{}",
|
log.info("【指令处理】前端{}于{}控制设备{}的{}功能,指令:{}",
|
||||||
clientId, LocalDateTime.now(), deviceId, funcType, payload);
|
clientId, LocalDateTime.now(), deviceId, funcType, payload);
|
||||||
|
|
||||||
// 4. 转发指令到设备
|
|
||||||
String deviceTopic = "dtu/" + deviceId + "/down";
|
|
||||||
//todo
|
//todo
|
||||||
mqttMessageSender.publish(deviceTopic, payload);
|
mqttMessageSender.publish(deviceTopic, payload);
|
||||||
// testAutoOffTask(deviceId,funcCodeMap);
|
|
||||||
|
|
||||||
SysAgriInfo agriInfo = sysAgriInfoService.lambdaQuery()
|
SysAgriInfo agriInfo = sysAgriInfoService.lambdaQuery()
|
||||||
.eq(SysAgriInfo::getImei, deviceId)
|
.eq(SysAgriInfo::getImei, deviceId)
|
||||||
|
|
@ -159,7 +171,11 @@ public class FrontendControlHandler {
|
||||||
logDto.setLockAcquired(1);
|
logDto.setLockAcquired(1);
|
||||||
logDto.setLockHolder(clientId);
|
logDto.setLockHolder(clientId);
|
||||||
logDto.setExecResult(1);
|
logDto.setExecResult(1);
|
||||||
sysDevOperLogService.save(logDto);
|
logDto.setCreateBy("手动控制");
|
||||||
|
boolean save = sysDevOperLogService.save(logDto);
|
||||||
|
// if (save) {
|
||||||
|
// testAutoOffTask(deviceId,funcCodeMap);
|
||||||
|
// }
|
||||||
log.info("【指令转发】前端{} → 设备{}的{}功能", clientId, deviceId, funcType);
|
log.info("【指令转发】前端{} → 设备{}的{}功能", clientId, deviceId, funcType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -169,7 +185,10 @@ public class FrontendControlHandler {
|
||||||
Integer funcValue = funcCodeMap.get(funcType);
|
Integer funcValue = funcCodeMap.get(funcType);
|
||||||
// 释放对应功能的分布式锁
|
// 释放对应功能的分布式锁
|
||||||
String lockKey = "lock:" + deviceId + ":" + funcType;
|
String lockKey = "lock:" + deviceId + ":" + funcType;
|
||||||
stringRedisTemplate.delete(lockKey);
|
Boolean delete = stringRedisTemplate.delete(lockKey);
|
||||||
|
if (delete) {
|
||||||
|
log.info("【设备控制锁删除成功!】");
|
||||||
|
}
|
||||||
|
|
||||||
// 回执成功且值=1时启动自动关闭任务(保留原有逻辑)
|
// 回执成功且值=1时启动自动关闭任务(保留原有逻辑)
|
||||||
if (StringUtils.hasText(funcType) && funcValue != null && funcValue == 1) {
|
if (StringUtils.hasText(funcType) && funcValue != null && funcValue == 1) {
|
||||||
|
|
@ -184,9 +203,27 @@ public class FrontendControlHandler {
|
||||||
if (autoOffSeconds > 0) {
|
if (autoOffSeconds > 0) {
|
||||||
mqttAutoOffManager.scheduleAutoOff(deviceId, funcType, autoOffSeconds);
|
mqttAutoOffManager.scheduleAutoOff(deviceId, funcType, autoOffSeconds);
|
||||||
log.debug("【自动关任务】标记需要执行,deviceId={}, funcType={}, delay={}s", deviceId, funcType, autoOffSeconds);
|
log.debug("【自动关任务】标记需要执行,deviceId={}, funcType={}, delay={}s", deviceId, funcType, autoOffSeconds);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
log.debug("【自动关任务】标记不符合执行运行时间未配置,deviceId={}, funcType={}, delay={}s", deviceId, funcType, autoOffSeconds);
|
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) {
|
if (StringUtils.hasText(funcType) && funcValue != null && funcValue == 0) {
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ public class MqttAutoOffManager {
|
||||||
@Value("${spring.mqtt.auto-off-thread-pool-size:5}")
|
@Value("${spring.mqtt.auto-off-thread-pool-size:5}")
|
||||||
private int autoOffThreadPoolSize;
|
private int autoOffThreadPoolSize;
|
||||||
|
|
||||||
@Value("${dtu-ctl-lock-ttl}")
|
@Value("${spring.mqtt.dtu-ctl-lock-ttl}")
|
||||||
private int dtuCtlLockTTL;
|
private int dtuCtlLockTTL;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|
@ -191,7 +191,7 @@ public class MqttAutoOffManager {
|
||||||
try {
|
try {
|
||||||
runAutoOff(deviceId, funcType);
|
runAutoOff(deviceId, funcType);
|
||||||
} catch (Exception e) {
|
} 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);
|
log.error("【自动关任务】执行失败,deviceId={}, funcType={}", deviceId, funcType, e);
|
||||||
} finally {
|
} finally {
|
||||||
// 任务执行完成后移除映射
|
// 任务执行完成后移除映射
|
||||||
|
|
@ -226,7 +226,7 @@ public class MqttAutoOffManager {
|
||||||
latestObj = JSON.parseObject(latest);
|
latestObj = JSON.parseObject(latest);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
skipReason = "【自动关任务】执行报错-解析异常";
|
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);
|
log.warn("【自动关任务】最新状态JSON解析失败,跳过:deviceId={}, funcType={}", deviceId, funcType);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -244,7 +244,9 @@ public class MqttAutoOffManager {
|
||||||
} catch (Exception ignore) {
|
} catch (Exception ignore) {
|
||||||
skipReason = "【自动关任务】最新状态功能码获取失败";
|
skipReason = "【自动关任务】最新状态功能码获取失败";
|
||||||
}
|
}
|
||||||
|
if (current == null || current!=1) {
|
||||||
|
skipReason = "【自动关任务】检测未运行或状态未知";
|
||||||
|
}
|
||||||
sysDevOperLogService.lambdaUpdate()
|
sysDevOperLogService.lambdaUpdate()
|
||||||
.eq(SysDevOperLog::getImei, deviceId)
|
.eq(SysDevOperLog::getImei, deviceId)
|
||||||
.eq(SysDevOperLog::getFuncCode, funcType)
|
.eq(SysDevOperLog::getFuncCode, funcType)
|
||||||
|
|
@ -256,6 +258,7 @@ public class MqttAutoOffManager {
|
||||||
.last("LIMIT 1")
|
.last("LIMIT 1")
|
||||||
.set(SysDevOperLog::getExecResult,1)
|
.set(SysDevOperLog::getExecResult,1)
|
||||||
.set(SysDevOperLog::getLatestState, latest)
|
.set(SysDevOperLog::getLatestState, latest)
|
||||||
|
.set(SysDevOperLog::getUpdateBy,"自动关")
|
||||||
.set(!skipReason.isEmpty(), SysDevOperLog::getSkipReason, skipReason)
|
.set(!skipReason.isEmpty(), SysDevOperLog::getSkipReason, skipReason)
|
||||||
.update();
|
.update();
|
||||||
|
|
||||||
|
|
@ -289,6 +292,7 @@ public class MqttAutoOffManager {
|
||||||
logDto.setLockHolder("autoOff");
|
logDto.setLockHolder("autoOff");
|
||||||
logDto.setExecResult(1);
|
logDto.setExecResult(1);
|
||||||
logDto.setLatestState(latest);
|
logDto.setLatestState(latest);
|
||||||
|
logDto.setCreateBy("自动关");
|
||||||
logDto.setTaskStatus(getFutureStatus().toString());
|
logDto.setTaskStatus(getFutureStatus().toString());
|
||||||
sysDevOperLogService.save(logDto);
|
sysDevOperLogService.save(logDto);
|
||||||
log.info("【自动关任务】检测仍在运行,已下发关闭:deviceId={}, funcType={}, payload={}", deviceId, funcType, down.toJSONString());
|
log.info("【自动关任务】检测仍在运行,已下发关闭:deviceId={}, funcType={}, payload={}", deviceId, funcType, down.toJSONString());
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,7 @@ public class MqttClientManager implements SmartLifecycle {
|
||||||
|
|
||||||
log.error("【MQTT连接异常】连接断开,clientId:{},原因:{}",
|
log.error("【MQTT连接异常】连接断开,clientId:{},原因:{}",
|
||||||
safeClientId(), (cause == null ? "unknown" : cause.getMessage()), cause);
|
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自动重连会接管重连过程
|
// 【方案A】不再触发自写重连;Paho自动重连会接管重连过程
|
||||||
// 这里只记录日志即可
|
// 这里只记录日志即可
|
||||||
if (isRunning.get()) {
|
if (isRunning.get()) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.agri.framework.web.dispatcher;
|
package com.agri.framework.web.dispatcher;
|
||||||
|
|
||||||
|
import com.agri.common.utils.wechat.WxUtil;
|
||||||
import com.agri.framework.interceptor.DeviceStatusHandler;
|
import com.agri.framework.interceptor.DeviceStatusHandler;
|
||||||
import com.agri.framework.interceptor.FrontendControlHandler;
|
import com.agri.framework.interceptor.FrontendControlHandler;
|
||||||
import com.agri.framework.interceptor.FrontendOnlineHandler;
|
import com.agri.framework.interceptor.FrontendOnlineHandler;
|
||||||
|
|
@ -64,6 +65,7 @@ public class MqttMessageDispatcher {
|
||||||
}
|
}
|
||||||
// todo 是否加回复主题??
|
// todo 是否加回复主题??
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
WxUtil.pushText("【MQTT消息处理异常】\n topic: "+ topic+"\n cause: "+e);
|
||||||
log.error("【MQTT消息处理异常】topic={}", topic, e);
|
log.error("【MQTT消息处理异常】topic={}", topic, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue