fix(ops): 修复按键播报延迟和循环停止失败问题
Some checks failed
Java CI with Maven / build (11) (push) Has been cancelled
Java CI with Maven / build (17) (push) Has been cancelled
Java CI with Maven / build (8) (push) Has been cancelled

1. 播报间隔从6秒缩短为3秒
2. stopLoop 清除播报间隔锁,使后续播报可立即发送
3. 按键触发的播报改用 broadcastDirect 直接下发,不走队列

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
lzh
2026-02-26 18:04:36 +08:00
parent b4de9d0df8
commit c21c77c758
3 changed files with 22 additions and 10 deletions

View File

@@ -7,6 +7,7 @@ import com.viewsh.module.ops.dal.mysql.workorder.OpsOrderMapper;
import com.viewsh.module.ops.enums.WorkOrderStatusEnum;
import com.viewsh.module.ops.environment.constants.CleanNotificationConstants;
import com.viewsh.module.ops.environment.integration.dto.CleanOrderAuditEventDTO;
import com.viewsh.module.ops.environment.service.voice.TtsQueueMessage;
import com.viewsh.module.ops.environment.service.voice.VoiceBroadcastService;
import com.viewsh.module.ops.infrastructure.log.enumeration.EventDomain;
import com.viewsh.module.ops.infrastructure.log.enumeration.EventLevel;
@@ -163,6 +164,9 @@ public class CleanOrderAuditEventHandler implements RocketMQListener<String> {
/**
* 处理查询事件 (IOT_BUTTON_QUERY)
* <p>
* 查询事件仅播报当前工单地点信息,不涉及循环播报停止和状态流转。
* 循环播报的停止由确认路径CleanOrderEventListener.handleConfirmed负责。
*/
private void handleQueryEvent(CleanOrderAuditEventDTO event) {
log.info("[CleanOrderAuditEventHandler] Handling query event: eventId={}", event.getEventId());
@@ -196,20 +200,21 @@ public class CleanOrderAuditEventHandler implements RocketMQListener<String> {
// 3. 构建 TTS 文本(使用统一模板构建器)
String ttsText = CleanNotificationConstants.VoiceBuilder.buildQuery(currentAreaName, pendingCount.intValue());
// 4. 下发 TTS
// 4. 直接下发 TTS(按键响应需立即播报,不走队列)
Long orderId = currentOrder != null ? currentOrder.getId() : null;
sendTts(deviceId, ttsText, orderId);
}
/**
* 下发 TTS 语音播报
* 下发 TTS 语音播报(直接发送,不走队列,按键响应需立即播报)
*/
private void sendTts(Long deviceId, String text, Long orderId) {
try {
voiceBroadcastService.broadcastInOrder(deviceId, text, orderId);
log.info("[CleanOrderAuditEventHandler] TTS 下发成功: deviceId={}, text={}", deviceId, text);
voiceBroadcastService.broadcastDirect(deviceId, text,
TtsQueueMessage.TTS_FLAG_URGENT, orderId);
log.info("[CleanOrderAuditEventHandler] TTS 直接下发成功: deviceId={}, text={}", deviceId, text);
} catch (Exception e) {
log.error("[CleanOrderAuditEventHandler] TTS 下发异常: deviceId={}", deviceId, e);
log.error("[CleanOrderAuditEventHandler] TTS 直接下发异常: deviceId={}", deviceId, e);
}
}

View File

@@ -15,6 +15,7 @@ import com.viewsh.module.ops.environment.dal.dataobject.workorder.OpsOrderCleanE
import com.viewsh.module.ops.environment.dal.mysql.workorder.OpsOrderCleanExtMapper;
import com.viewsh.module.ops.environment.dal.redis.TrafficActiveOrderRedisDAO;
import com.viewsh.module.ops.environment.service.cleanorder.CleanOrderService;
import com.viewsh.module.ops.environment.service.voice.TtsQueueMessage;
import com.viewsh.module.ops.environment.service.voice.VoiceBroadcastService;
import com.viewsh.module.ops.infrastructure.log.enumeration.EventDomain;
import com.viewsh.module.ops.infrastructure.log.recorder.EventLogRecord;
@@ -276,13 +277,14 @@ public class CleanOrderEventListener {
// 1. 停止循环播报
voiceBroadcastService.stopLoop(deviceId);
// 2. 播报地点信息
// 2. 直接播报地点信息(不走队列,按键响应需立即播报)
OpsOrderDO order = opsOrderMapper.selectById(orderId);
String areaName = CleanNotificationConstants.VoiceBuilder.getAreaName(
order != null ? order.getLocation() : null);
String locationMessage = String.format(
CleanNotificationConstants.VoiceTemplate.QUERY_HAS_ORDER, areaName);
playVoice(deviceId, locationMessage, orderId);
voiceBroadcastService.broadcastDirect(deviceId, locationMessage,
TtsQueueMessage.TTS_FLAG_URGENT, orderId);
}
log.info("[CleanOrderEventListener] 工单已确认: orderId={}, deviceId={}", orderId, deviceId);
@@ -434,10 +436,12 @@ public class CleanOrderEventListener {
updateExt.setCompletedTime(LocalDateTime.now());
cleanExtMapper.insertOnDuplicateKeyUpdate(updateExt);
// 2. 停止循环播报 + 语音播报通知保洁员工单已取消(取消是异常情况,需要通知)
// 2. 停止循环播报 + 直接播报通知保洁员工单已取消(取消是异常情况,需要通知)
if (deviceId != null) {
voiceBroadcastService.stopLoop(deviceId);
playVoice(deviceId, CleanNotificationConstants.VoiceTemplate.ORDER_CANCELLED, orderId);
voiceBroadcastService.broadcastDirect(deviceId,
CleanNotificationConstants.VoiceTemplate.ORDER_CANCELLED,
TtsQueueMessage.TTS_FLAG_URGENT, orderId);
}
// 3. 自动调度下一个等待任务(如果有 assignee

View File

@@ -51,7 +51,7 @@ public class TtsQueueConsumer {
@Value("${ops.tts.queue.enabled:true}")
private boolean queueEnabled;
@Value("${ops.tts.queue.interval-ms:6000}")
@Value("${ops.tts.queue.interval-ms:3000}")
private long broadcastIntervalMs;
@Value("${ops.tts.queue.max-queue-size:50}")
@@ -376,6 +376,9 @@ public class TtsQueueConsumer {
public void stopLoop(Long deviceId) {
String loopKey = LOOP_KEY_PREFIX + deviceId;
Boolean deleted = redisTemplate.delete(loopKey);
// 清除播报间隔锁,使后续播报(如地点播报)可以立即发送
String lockKey = LOCK_KEY_PREFIX + deviceId;
redisTemplate.delete(lockKey);
// 从队列中移除循环消息,保留非循环消息(如取消播报、待办播报等)
int removed = removeLoopMessages(deviceId);
log.info("[TTS队列] 停止循环播报: deviceId={}, loopKeyDeleted={}, removedMessages={}", deviceId, deleted, removed);