feat(ops,iot): 工单语音播报循环机制 + 统一按键逻辑
核心改动: - 新增循环播报机制:DISPATCHED 状态持续播报"工单来啦"直到按键确认 - 统一按键逻辑:confirmKeyId 和 queryKeyId 都路由到同一处理逻辑, 根据工单状态智能判断行为(确认/查询/无工单提示) - ARRIVED/COMPLETED 状态静默不播报,CANCELLED 保留取消播报 - 修复 P0:确认去重后按键不再静默,改为发查询事件给反馈 - 修复 P0:PAUSED 状态(P0打断)时停止被打断工单的循环播报 - 修复 P1:handleCompleted 补全 deviceId 兜底逻辑 - 修复 P1:stopLoop 只移除循环消息,保留非循环消息 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -74,74 +74,62 @@ public class ButtonEventRuleProcessor {
|
||||
|
||||
log.debug("[ButtonEvent] 按键解析成功:deviceId={}, buttonId={}", deviceId, buttonId);
|
||||
|
||||
// 4. 匹配按键类型并处理
|
||||
if (buttonId.equals(buttonConfig.getConfirmKeyId())) {
|
||||
// 确认键
|
||||
handleConfirmButton(deviceId, buttonId);
|
||||
} else if (buttonId.equals(buttonConfig.getQueryKeyId())) {
|
||||
// 查询键
|
||||
handleQueryButton(deviceId, buttonId);
|
||||
// 4. 匹配按键类型并处理(确认键和查询键统一路由到同一逻辑)
|
||||
if (buttonId.equals(buttonConfig.getConfirmKeyId())
|
||||
|| buttonId.equals(buttonConfig.getQueryKeyId())) {
|
||||
// 所有已知按键统一走绿色按键逻辑(根据工单状态智能判断行为)
|
||||
handleGreenButton(deviceId, buttonId);
|
||||
} else {
|
||||
log.debug("[ButtonEvent] 未配置的按键:deviceId={}, buttonId={}", deviceId, buttonId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理确认按键
|
||||
* 处理绿色按键(统一按键逻辑)
|
||||
* <p>
|
||||
* 保洁员按下确认键,确认接收工单
|
||||
* 根据当前工单状态智能判断行为:
|
||||
* - 无工单:发布查询事件(Ops 端播报"没有工单")
|
||||
* - DISPATCHED:发布确认事件(触发确认状态转换 + 停止循环 + 播报地点)
|
||||
* - CONFIRMED/ARRIVED:发布查询事件(播报地点)
|
||||
* - 其他状态:发布查询事件(兜底处理)
|
||||
*/
|
||||
private void handleConfirmButton(Long deviceId, Integer buttonId) {
|
||||
|
||||
log.info("[ButtonEvent] 确认键按下:deviceId={}, buttonId={}", deviceId, buttonId);
|
||||
|
||||
// 1. 查询设备当前工单
|
||||
BadgeDeviceStatusRedisDAO.OrderInfo currentOrder = badgeDeviceStatusRedisDAO.getCurrentOrder(deviceId);
|
||||
if (currentOrder == null) {
|
||||
log.warn("[ButtonEvent] 设备无当前工单,跳过确认:deviceId={}", deviceId);
|
||||
return;
|
||||
}
|
||||
|
||||
Long orderId = currentOrder.getOrderId();
|
||||
|
||||
// 2. 防重复检查(短时间内同一工单的确认操作去重)
|
||||
String dedupKey = String.format("iot:clean:button:dedup:confirm:%s:%s", deviceId, orderId);
|
||||
Boolean firstTime = stringRedisTemplate.opsForValue()
|
||||
.setIfAbsent(dedupKey, "1", 10, java.util.concurrent.TimeUnit.SECONDS);
|
||||
|
||||
if (!firstTime) {
|
||||
log.info("[ButtonEvent] 确认操作重复,跳过:deviceId={}, orderId={}", deviceId, orderId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 发布工单确认事件
|
||||
publishConfirmEvent(deviceId, orderId, buttonId);
|
||||
|
||||
log.info("[ButtonEvent] 发布工单确认事件:deviceId={}, orderId={}", deviceId, orderId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理查询按键
|
||||
* <p>
|
||||
* 保洁员按下查询键,查询当前工单信息
|
||||
*/
|
||||
private void handleQueryButton(Long deviceId, Integer buttonId) {
|
||||
|
||||
log.info("[ButtonEvent] 查询键按下:deviceId={}, buttonId={}", deviceId, buttonId);
|
||||
private void handleGreenButton(Long deviceId, Integer buttonId) {
|
||||
log.info("[ButtonEvent] 绿色按键按下:deviceId={}, buttonId={}", deviceId, buttonId);
|
||||
|
||||
// 1. 查询设备当前工单
|
||||
BadgeDeviceStatusRedisDAO.OrderInfo currentOrder = badgeDeviceStatusRedisDAO.getCurrentOrder(deviceId);
|
||||
if (currentOrder == null) {
|
||||
// 无工单 → 发布查询事件(Ops 端播报"没有工单")
|
||||
log.info("[ButtonEvent] 设备无当前工单:deviceId={}", deviceId);
|
||||
// 发布查询结果事件(无工单)
|
||||
publishQueryEvent(deviceId, null, buttonId, "当前无工单");
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 发布查询事件
|
||||
publishQueryEvent(deviceId, currentOrder.getOrderId(), buttonId, "查询当前工单");
|
||||
Long orderId = currentOrder.getOrderId();
|
||||
String orderStatus = currentOrder.getStatus();
|
||||
|
||||
log.info("[ButtonEvent] 发布工单查询事件:deviceId={}, orderId={}", deviceId, currentOrder.getOrderId());
|
||||
// 2. 根据工单状态智能分派
|
||||
if ("DISPATCHED".equals(orderStatus)) {
|
||||
// DISPATCHED → 发布确认事件(触发确认 + 停止循环 + 播报地点)
|
||||
// 防重复检查
|
||||
String dedupKey = String.format("iot:clean:button:dedup:confirm:%s:%s", deviceId, orderId);
|
||||
Boolean firstTime = stringRedisTemplate.opsForValue()
|
||||
.setIfAbsent(dedupKey, "1", 10, java.util.concurrent.TimeUnit.SECONDS);
|
||||
|
||||
if (!Boolean.TRUE.equals(firstTime)) {
|
||||
// 重复确认不再静默,改为发查询事件给保洁员反馈(播报地点)
|
||||
log.info("[ButtonEvent] 确认操作重复,转为查询:deviceId={}, orderId={}", deviceId, orderId);
|
||||
publishQueryEvent(deviceId, orderId, buttonId, "重复确认,查询当前工单");
|
||||
return;
|
||||
}
|
||||
|
||||
publishConfirmEvent(deviceId, orderId, buttonId);
|
||||
log.info("[ButtonEvent] DISPATCHED状态,发布确认事件:deviceId={}, orderId={}", deviceId, orderId);
|
||||
} else {
|
||||
// CONFIRMED / ARRIVED / 其他状态 → 发布查询事件(播报地点)
|
||||
publishQueryEvent(deviceId, orderId, buttonId, "查询当前工单");
|
||||
log.info("[ButtonEvent] {}状态,发布查询事件:deviceId={}, orderId={}", orderStatus, deviceId, orderId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user