@ -201,88 +201,130 @@ public class DeviceXinghanBizService {
* @return
*/
public int sendAlarmMessage ( AppDeviceSendMsgBo bo ) {
List < Long > deviceIds = bo . getDeviceIds ( ) ;
// 1. 简化非空检查和抛出异常
if ( deviceIds = = null | | deviceIds . isEmpty ( ) ) {
throw new ServiceException ( " 请选择设备 " ) ;
}
QueryWrapper < Device > queryWrapper = new QueryWrapper < > ( ) ;
// 使用 in 语句根据id集合查询
queryWrapper . in ( " id " , deviceIds ) ;
// 2. 将批量查询设备,减少数据库交互次数
List < Device > devices = deviceMapper . selectList ( queryWrapper ) ;
if ( devices . size ( ) ! = deviceIds . size ( ) ) {
// 如果查询回来的设备数量不一致,说明有设备不存在,此处可以优化为更详细的提示
throw new ServiceException ( " 部分设备不存在 " ) ;
}
try {
List < Long > deviceIds = bo . getD eviceId s( ) ;
if ( deviceIds = = null | | deviceIds . isEmpty ( ) ) {
throw new Ser viceException ( " 请选择设备 " ) ;
for ( Device device : d evices) {
String deviceImei = device . getDeviceImei ( ) ;
String deviceName = de vice. getDeviceName ( ) ;
// 3. 在循环中进行设备状态检查,快速失败
if ( isDeviceOffline ( deviceImei ) ) {
// 如果设备离线,可以选择继续处理下一个设备,或者抛出异常。这里选择抛出异常。
throw new ServiceException ( deviceName + " , 设备已断开连接 " ) ;
}
// 4. 将Redis和MQTT操作封装在一个方法中, 提高可读性
sendSingleAlarmMessage ( device , bo . getSendMsg ( ) ) ;
// 5. 批量更新设备状态,提高效率
UpdateWrapper < Device > updateWrapper = new UpdateWrapper < > ( ) ;
updateWrapper . eq ( " id " , device . getId ( ) )
. eq ( " binding_user_id " , AppLoginHelper . getUserId ( ) )
. set ( " send_msg " , bo . getSendMsg ( ) ) ;
deviceMapper . update ( updateWrapper ) ;
// 6. 记录操作日志
recordDeviceLog ( device . getId ( ) , deviceName , " 发送紧急通知 " , bo . getSendMsg ( ) , AppLoginHelper . getUserId ( ) ) ;
}
for ( Long deviceId : deviceIds ) {
Device device = deviceMapper . selectById ( deviceId ) ;
if ( device = = null ) {
throw new ServiceException ( " 设备不存在 " + deviceId ) ;
}
if ( isDeviceOffline ( device . getDeviceImei ( ) ) ) {
throw new ServiceException ( device . getDeviceName ( ) + " ,设备已断开连接 " ) ;
}
try {
RedisUtils . setCacheObject ( GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + device . getDeviceImei ( ) + DEVICE_ALARM_MESSAGE_KEY_PREFIX , bo . getSendMsg ( ) , Duration . ofSeconds ( 5 * 60L ) ) ;
Map < String , Object > payload = Map . of ( " ins_BreakNews " ,
Collections . singletonList ( 0 ) ) ;
String topic = MqttConstants . GLOBAL_PUB_KEY + device . getDeviceImei ( ) ;
String json = JsonUtils . toJsonString ( payload ) ;
try {
mqttGateway . sendMsgToMqtt ( topic , 1 , json ) ;
} catch ( Exception e ) {
log . error ( " 发送紧急通知失败, topic={}, payload={} " , topic , json , e ) ;
throw new ServiceException ( " 发送紧急通知失败: " + e . getMessage ( ) ) ;
}
log . info ( " 发送紧急通知=>topic:{},payload:{} " , MqttConstants . GLOBAL_PUB_KEY + device . getDeviceImei ( ) , json ) ;
UpdateWrapper < Device > updateWrapper = new UpdateWrapper < > ( ) ;
updateWrapper . eq ( " id " , deviceId )
. eq ( " binding_user_id " , AppLoginHelper . getUserId ( ) )
. set ( " send_msg " , bo . getSendMsg ( ) ) ;
deviceMapper . update ( updateWrapper ) ;
recordDeviceLog ( device . getId ( ) , device . getDeviceName ( ) , " 发送紧急通知 " , bo . getSendMsg ( ) , AppLoginHelper . getUserId ( ) ) ;
} catch ( Exception e ) {
log . info ( " 设备发送告警信息信息失败:{} " , deviceId ) ;
throw new ServiceException ( " 设备发送告警信息信息失败 " ) ;
}
}
} catch ( Exception e ) {
e . printStackTrace ( ) ;
} catch ( ServiceException e ) {
// 捕获并重新抛出自定义异常,避免内层异常被外层泛化捕获
log . error ( " 发送告警信息指令失败: {} " , e . getMessage ( ) , e ) ;
throw e ;
} catch ( Exception e ) {
log . error ( " 发送告警信息指令发生未知错误 " , e ) ;
throw new ServiceException ( " 发送告警信息指令失败 " ) ;
}
return 1 ;
}
/* ---------------------------------- 私有通用方法 ---------------------------------- */
private void sendCommand ( DeviceInstructDto dto ,
String payloadKey , String deviceAction ) {
long deviceId = dto . getDeviceId ( ) ;
Device d evice = deviceMapper . selectById ( deviceId ) ;
if ( device = = null ) {
throw new ServiceException ( " 设备不存在 " ) ;
}
if ( isDeviceOffline ( device . getDeviceImei ( ) ) ) {
throw new ServiceException ( " 设备已断开连接: " + device . getDeviceName ( ) ) ;
}
/**
* 封装单个设备发送告警信息的逻辑
*/
private void sendSingleAlarmMessage ( D evice device, String message ) {
String deviceImei = device . getDeviceImei ( ) ;
Integer value = Integer . parseInt ( dto . getInstructValue ( ) ) ;
// 缓存告警消息到Redis
RedisUtils . setCacheObject ( GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + deviceImei + DEVICE_ALARM_MESSAGE_KEY_PREFIX , message , Duration . ofSeconds ( 5 * 60L ) ) ;
Map < String , Object > payload = Map . of ( payloadKey ,
Collections . singletonList ( value ) ) ;
String topic = MqttConstants . GLOBAL_PUB_KEY + device . getDeviceImei ( ) ;
// 构建并发送MQTT消息
Map < String , Object > payload = Map . of ( " ins_BreakNews " , Collections . singletonList ( 0 ) ) ;
String topic = MqttConstants . GLOBAL_PUB_KEY + deviceImei ;
String json = JsonUtils . toJsonString ( payload ) ;
try {
mqttGateway . sendMsgToMqtt ( topic , 1 , json ) ;
log . info ( " 发送紧急通知成功 => topic:{}, payload:{} " , topic , json ) ;
} catch ( Exception e ) {
log . error ( " 发送紧急通知失败, topic={}, payload={} " , topic , json , e ) ;
throw new ServiceException ( " 发送紧急通知失败: " + e . getMessage ( ) ) ;
}
}
/**
* 发送设备控制指令
*
* @param dto 设备指令数据传输对象, 包含设备ID和指令值等信息
* @param payloadKey 指令负载数据的键名
* @param deviceAction 设备操作类型描述
*/
private void sendCommand ( DeviceInstructDto dto , String payloadKey , String deviceAction ) {
long deviceId = dto . getDeviceId ( ) ;
// 1. 使用Optional简化空值检查, 使代码更简洁
Device device = Optional . ofNullable ( deviceMapper . selectById ( deviceId ) )
. orElseThrow ( ( ) - > new ServiceException ( " 设备不存在 " ) ) ;
String deviceImei = device . getDeviceImei ( ) ;
String deviceName = device . getDeviceName ( ) ;
// 2. 提前进行设备状态检查,逻辑更清晰
if ( isDeviceOffline ( deviceImei ) ) {
throw new ServiceException ( " 设备已断开连接: " + deviceName ) ;
}
// 3. 统一处理类型转换异常, 避免在业务逻辑中混杂try-catch
int value ;
try {
value = Integer . parseInt ( dto . getInstructValue ( ) ) ;
} catch ( NumberFormatException e ) {
throw new IllegalArgumentException ( " 指令值格式不正确,必须为整数。 " , e ) ;
}
// 4. 使用Map.of()或Map.ofEntries()创建不可变Map, 更简洁且线程安全
Map < String , List < Integer > > payload = Map . of ( payloadKey , List . of ( value ) ) ;
String topic = MqttConstants . GLOBAL_PUB_KEY + deviceImei ;
String json = JsonUtils . toJsonString ( payload ) ;
try {
mqttGateway . sendMsgToMqtt ( topic , 1 , json ) ;
log . info ( " 发送指令成功 => topic:{}, payload:{} " , topic , json ) ;
} catch ( Exception e ) {
log . error ( " 发送指令失败, topic={}, payload={} " , topic , json , e ) ;
throw new ServiceException ( " 发送指令失败: " + e . getMessage ( ) ) ;
}
log . info ( " 发送指令成功 => topic:{}, payload:{} " , topic , json ) ;
// 5. 将日志记录和描述解析放在try-catch块之外, 确保无论是否成功发送指令都能执行
String content = resolveGradeDesc ( " ins_DetectGrade " , value ) ;
recordDeviceLog ( device . getId ( ) ,
device. getDeviceName ( ) ,
deviceName ,
deviceAction ,
content ,
AppLoginHelper . getUserId ( ) ) ;