Compare commits
2 Commits
ab1cc2bc62
...
20ea25cf55
| Author | SHA1 | Date | |
|---|---|---|---|
| 20ea25cf55 | |||
| 13c9b6564f |
@@ -62,9 +62,45 @@ public class CleanRuleProcessorManager {
|
||||
log.debug("[processMessage][设备({}) 处理{}上报,数据数量: {}]",
|
||||
deviceId, "thing.event.post".equals(method) ? "事件" : "属性", data.size());
|
||||
|
||||
// 3. 顺序处理各数据项(与场景规则处理器保持一致)
|
||||
data.forEach((identifier, value) ->
|
||||
processDataSafely(deviceId, identifier, value));
|
||||
// 3. 判断是属性上报还是事件上报
|
||||
if (IotDeviceMessageMethodEnum.EVENT_POST.getMethod().equals(method)) {
|
||||
// 事件上报:params 结构为 {identifier: "...", eventTime: ..., params: {...}}
|
||||
processEventData(deviceId, data);
|
||||
} else {
|
||||
// 属性上报:直接遍历 key-value
|
||||
data.forEach((identifier, value) ->
|
||||
processDataSafely(deviceId, identifier, value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理事件上报数据
|
||||
* <p>
|
||||
* 事件上报的 params 结构:
|
||||
* {
|
||||
* "identifier": "button_event",
|
||||
* "eventTime": 1234567890,
|
||||
* "params": { keyId: 1, keyState: 1 }
|
||||
* }
|
||||
*/
|
||||
private void processEventData(Long deviceId, Map<String, Object> data) {
|
||||
String identifier = (String) data.get("identifier");
|
||||
if (identifier == null) {
|
||||
log.warn("[processEventData][设备({}) 事件缺少 identifier]", deviceId);
|
||||
return;
|
||||
}
|
||||
|
||||
Object params = data.get("params");
|
||||
log.debug("[processEventData][设备({}) 事件: {}, params: {}]", deviceId, identifier, params);
|
||||
|
||||
// 路由到对应处理器
|
||||
switch (identifier) {
|
||||
case "button_event" ->
|
||||
buttonEventRuleProcessor.processPropertyChange(deviceId, identifier, params);
|
||||
default -> {
|
||||
// 其他事件忽略
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -222,12 +222,28 @@ public class ButtonEventRuleProcessor {
|
||||
|
||||
/**
|
||||
* 解析按键ID
|
||||
* <p>
|
||||
* 支持两种格式:
|
||||
* 1. 属性上报:value 直接是按键ID(如 1)
|
||||
* 2. 事件上报:value 是 Map,包含 keyId 字段(如 {keyId: 1, keyState: 1})
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private Integer parseButtonId(Object value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 事件上报格式:value 是 Map,包含 keyId 字段
|
||||
if (value instanceof Map) {
|
||||
Map<String, Object> map = (Map<String, Object>) value;
|
||||
Object keyId = map.get("keyId");
|
||||
if (keyId instanceof Number) {
|
||||
return ((Number) keyId).intValue();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 属性上报格式:value 直接是按键ID
|
||||
if (value instanceof Number) {
|
||||
return ((Number) value).intValue();
|
||||
}
|
||||
|
||||
@@ -40,14 +40,6 @@ public interface CleanOrderService {
|
||||
*/
|
||||
void enqueueOrderOnly(Long orderId, Long cleanerId);
|
||||
|
||||
/**
|
||||
* 入队并立即推送(空闲保洁员,状态:PENDING → QUEUED → DISPATCHED)
|
||||
*
|
||||
* @param orderId 工单ID
|
||||
* @param cleanerId 保洁员ID
|
||||
*/
|
||||
void enqueueAndDispatch(Long orderId, Long cleanerId);
|
||||
|
||||
/**
|
||||
* 推送工单到工牌(状态:QUEUED → DISPATCHED)
|
||||
* 支持并发控制,防止重复推送
|
||||
|
||||
@@ -179,44 +179,6 @@ public class CleanOrderServiceImpl implements CleanOrderService {
|
||||
log.info("工单已入队: orderId={}, deviceId={}", orderId, deviceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void enqueueAndDispatch(Long orderId, Long deviceId) {
|
||||
enqueueAndDispatch(orderId, deviceId, false);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void enqueueAndDispatch(Long orderId, Long deviceId, boolean isUrgent) {
|
||||
// 查询工单
|
||||
OpsOrderDO order = opsOrderMapper.selectById(orderId);
|
||||
if (order == null) {
|
||||
log.error("工单不存在: orderId={}", orderId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isUrgent) {
|
||||
// P0紧急任务:使用紧急插队
|
||||
DispatchResult result = dispatchEngine.urgentInterrupt(orderId, deviceId);
|
||||
log.warn("P0紧急派单结果: orderId={}, success={}", orderId, result.isSuccess());
|
||||
} else {
|
||||
// 普通任务:正常派单
|
||||
OrderTransitionRequest request = OrderTransitionRequest.builder()
|
||||
.orderId(orderId)
|
||||
.targetStatus(WorkOrderStatusEnum.DISPATCHED)
|
||||
.assigneeId(deviceId)
|
||||
.operatorType(OperatorTypeEnum.SYSTEM)
|
||||
.operatorId(deviceId)
|
||||
.reason("自动派单")
|
||||
.build();
|
||||
|
||||
orderLifecycleManager.dispatch(request);
|
||||
log.info("工单已派发: orderId={}, deviceId={}", orderId, deviceId);
|
||||
}
|
||||
|
||||
// 语音播报
|
||||
cleanOrderEventListener.sendNewOrderNotification(deviceId, orderId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void dispatchToCleaner(Long queueId) {
|
||||
|
||||
@@ -221,36 +221,6 @@ public class CleanOrderEndToEndTest {
|
||||
verify(opsOrderMapper, times(1)).insert(any(OpsOrderDO.class));
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// DP-01 ~ DP-03: 智能调度测试 (模拟)
|
||||
// ==========================================
|
||||
|
||||
@Test
|
||||
void testDP03_P0UrgentInterrupt() {
|
||||
injectField(cleanOrderService, "dispatchEngine", dispatchEngine);
|
||||
injectField(cleanOrderService, "opsOrderMapper", opsOrderMapper);
|
||||
|
||||
// 准备一个 P0 紧急工单
|
||||
Long orderId = 999L;
|
||||
Long cleanerId = 2001L;
|
||||
|
||||
OpsOrderDO order = OpsOrderDO.builder()
|
||||
.id(orderId)
|
||||
.priority(PriorityEnum.P0.getPriority())
|
||||
.build();
|
||||
orderDB.put(orderId, order);
|
||||
|
||||
// 模拟调度引擎返回成功
|
||||
when(dispatchEngine.urgentInterrupt(eq(orderId), eq(cleanerId)))
|
||||
.thenReturn(DispatchResult.success("P0插队成功", cleanerId));
|
||||
|
||||
// 执行派单
|
||||
cleanOrderService.enqueueAndDispatch(orderId, cleanerId, true);
|
||||
|
||||
// 验证
|
||||
verify(dispatchEngine).urgentInterrupt(eq(orderId), eq(cleanerId));
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// AV-01 ~ AV-03: 到岗校验测试
|
||||
// ==========================================
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package com.viewsh.module.ops.service.fsm;
|
||||
|
||||
import com.viewsh.module.ops.core.event.OrderEventPublisher;
|
||||
import com.viewsh.module.ops.core.event.OrderStateChangedEvent;
|
||||
import com.viewsh.module.ops.dal.dataobject.workorder.OpsOrderDO;
|
||||
import com.viewsh.module.ops.dal.mysql.workorder.OpsOrderMapper;
|
||||
import com.viewsh.module.ops.enums.OperatorTypeEnum;
|
||||
@@ -21,17 +19,16 @@ import java.util.*;
|
||||
* 职责:
|
||||
* 1. 管理工单状态转换规则
|
||||
* 2. 执行状态转换并记录事件
|
||||
* 3. 发布状态变更事件(通过事件发布器)
|
||||
* <p>
|
||||
* 设计原则:
|
||||
* - 单一职责:只负责状态转换规则验证和状态管理
|
||||
* - 不触发业务逻辑:业务逻辑通过事件订阅处理
|
||||
* - 事件驱动:状态变更后发布事件,业务方订阅处理
|
||||
* - 事件发布由 LifecycleManager 责任链中的 EventPublishHandler 统一处理
|
||||
* <p>
|
||||
* 变更说明:
|
||||
* - 移除了监听器机制(改为事件发布)
|
||||
* - 移除了监听器机制
|
||||
* - 状态机只负责状态转换验证和状态更新
|
||||
* - 业务逻辑通过 @EventListener 订阅事件处理
|
||||
* - 事件发布职责统一由 EventPublishHandler 处理,避免重复发布
|
||||
*
|
||||
* @author lzh
|
||||
*/
|
||||
@@ -45,12 +42,6 @@ public class OrderStateMachine {
|
||||
@Resource
|
||||
private OpsOrderEventService eventService;
|
||||
|
||||
/**
|
||||
* 事件发布器(用于发布状态变更事件)
|
||||
*/
|
||||
@Resource
|
||||
private OrderEventPublisher eventPublisher;
|
||||
|
||||
/**
|
||||
* 状态转换规则(清晰可见)
|
||||
* Key: 当前状态
|
||||
@@ -163,9 +154,6 @@ public class OrderStateMachine {
|
||||
remark
|
||||
);
|
||||
|
||||
// 7. 发布状态变更事件(替代监听器机制)
|
||||
publishStateChangedEvent(order, oldStatus, newStatus, operatorType, operatorId, remark);
|
||||
|
||||
log.info("工单状态转换成功: orderId={}, {} -> {}, operatorType={}, operatorId={}",
|
||||
order.getId(), oldStatus, newStatus, operatorType, operatorId);
|
||||
}
|
||||
@@ -259,37 +247,4 @@ public class OrderStateMachine {
|
||||
default -> "STATUS_CHANGE";
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布状态变更事件
|
||||
* <p>
|
||||
* 替代原有的监听器机制:
|
||||
* - 业务方通过 @EventListener 订阅事件
|
||||
* - 事件异步发布,不阻塞主流程
|
||||
*/
|
||||
private void publishStateChangedEvent(OpsOrderDO order,
|
||||
WorkOrderStatusEnum oldStatus,
|
||||
WorkOrderStatusEnum newStatus,
|
||||
OperatorTypeEnum operatorType,
|
||||
Long operatorId,
|
||||
String remark) {
|
||||
try {
|
||||
OrderStateChangedEvent event = OrderStateChangedEvent.builder()
|
||||
.orderId(order.getId())
|
||||
.orderType(order.getOrderType())
|
||||
.orderCode(order.getOrderCode())
|
||||
.oldStatus(oldStatus)
|
||||
.newStatus(newStatus)
|
||||
.operatorType(operatorType)
|
||||
.operatorId(operatorId)
|
||||
.eventTime(LocalDateTime.now())
|
||||
.remark(remark)
|
||||
.build();
|
||||
|
||||
eventPublisher.publishStateChanged(event);
|
||||
} catch (Exception e) {
|
||||
// 事件发布失败不应影响主流程
|
||||
log.error("发布状态变更事件失败: orderId={}", order.getId(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user