feat(ops): add-iot-clean-order-integration阶段2-ButtonEventRuleProcessor补充
This commit is contained in:
@@ -0,0 +1,295 @@
|
||||
package com.viewsh.module.iot.service.rule.clean.processor;
|
||||
|
||||
import com.viewsh.module.iot.core.integration.constants.CleanOrderTopics;
|
||||
import com.viewsh.module.iot.dal.dataobject.integration.clean.ButtonEventConfig;
|
||||
import com.viewsh.module.iot.dal.redis.clean.DeviceCurrentOrderRedisDAO;
|
||||
import com.viewsh.module.iot.service.integration.clean.CleanOrderIntegrationConfigService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.rocketmq.spring.core.RocketMQTemplate;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.messaging.support.MessageBuilder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 按键事件规则处理器
|
||||
* <p>
|
||||
* 监听设备按键事件上报,处理保洁员工牌的按键交互
|
||||
* <p>
|
||||
* 支持的按键类型:
|
||||
* - 确认键(confirmKeyId):保洁员确认接收工单
|
||||
* - 查询键(queryKeyId):保洁员查询当前工单信息
|
||||
*
|
||||
* @author AI
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ButtonEventRuleProcessor {
|
||||
|
||||
@Resource
|
||||
private CleanOrderIntegrationConfigService configService;
|
||||
|
||||
@Resource
|
||||
private DeviceCurrentOrderRedisDAO deviceCurrentOrderRedisDAO;
|
||||
|
||||
@Resource
|
||||
private RocketMQTemplate rocketMQTemplate;
|
||||
|
||||
/**
|
||||
* 处理按键事件属性上报
|
||||
* <p>
|
||||
* 在设备属性上报处理流程中调用此方法
|
||||
*
|
||||
* @param deviceId 设备ID
|
||||
* @param identifier 属性标识符(如 button_event)
|
||||
* @param propertyValue 属性值
|
||||
*/
|
||||
public void processPropertyChange(Long deviceId, String identifier, Object propertyValue) {
|
||||
// 1. 检查是否是按键事件属性
|
||||
if (!"button_event".equals(identifier)) {
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug("[ButtonEvent] 收到按键事件:deviceId={}, value={}", deviceId, propertyValue);
|
||||
|
||||
// 2. 获取配置
|
||||
CleanOrderIntegrationConfigService.AreaDeviceConfigWrapper configWrapper =
|
||||
getConfigWrapper(deviceId);
|
||||
|
||||
if (configWrapper == null || configWrapper.getConfig() == null) {
|
||||
log.debug("[ButtonEvent] 设备无配置:deviceId={}", deviceId);
|
||||
return;
|
||||
}
|
||||
|
||||
ButtonEventConfig buttonConfig = configWrapper.getConfig().getButtonEvent();
|
||||
if (buttonConfig == null || !buttonConfig.getEnabled()) {
|
||||
log.debug("[ButtonEvent] 未启用按键事件处理:deviceId={}", deviceId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 解析按键ID
|
||||
Integer buttonId = parseButtonId(propertyValue);
|
||||
if (buttonId == null) {
|
||||
log.warn("[ButtonEvent] 按键ID解析失败:deviceId={}, value={}", deviceId, propertyValue);
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug("[ButtonEvent] 按键解析成功:deviceId={}, buttonId={}", deviceId, buttonId);
|
||||
|
||||
// 4. 匹配按键类型并处理
|
||||
if (buttonId.equals(buttonConfig.getConfirmKeyId())) {
|
||||
// 确认键
|
||||
handleConfirmButton(configWrapper, buttonId);
|
||||
} else if (buttonId.equals(buttonConfig.getQueryKeyId())) {
|
||||
// 查询键
|
||||
handleQueryButton(configWrapper, buttonId);
|
||||
} else {
|
||||
log.debug("[ButtonEvent] 未配置的按键:deviceId={}, buttonId={}", deviceId, buttonId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理确认按键
|
||||
* <p>
|
||||
* 保洁员按下确认键,确认接收工单
|
||||
*/
|
||||
private void handleConfirmButton(CleanOrderIntegrationConfigService.AreaDeviceConfigWrapper configWrapper,
|
||||
Integer buttonId) {
|
||||
Long deviceId = configWrapper.getDeviceId();
|
||||
|
||||
log.info("[ButtonEvent] 确认键按下:deviceId={}, buttonId={}", deviceId, buttonId);
|
||||
|
||||
// 1. 查询设备当前工单
|
||||
DeviceCurrentOrderRedisDAO.OrderCacheInfo currentOrderJson = deviceCurrentOrderRedisDAO.getCurrentOrder(deviceId);
|
||||
if (currentOrderJson == null) {
|
||||
log.warn("[ButtonEvent] 设备无当前工单,跳过确认:deviceId={}", deviceId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 解析工单ID(简单解析,生产环境可用 JSON 库)
|
||||
Long orderId = extractOrderIdFromJson(currentOrderJson.getOrderId().toString());
|
||||
if (orderId == null) {
|
||||
log.warn("[ButtonEvent] 工单ID解析失败:deviceId={}, json={}", deviceId, currentOrderJson);
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 防重复检查(短时间内同一工单的确认操作去重)
|
||||
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;
|
||||
}
|
||||
|
||||
// 4. 发布工单确认事件
|
||||
publishConfirmEvent(configWrapper, orderId, buttonId);
|
||||
|
||||
log.info("[ButtonEvent] 发布工单确认事件:deviceId={}, orderId={}", deviceId, orderId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理查询按键
|
||||
* <p>
|
||||
* 保洁员按下查询键,查询当前工单信息
|
||||
*/
|
||||
private void handleQueryButton(CleanOrderIntegrationConfigService.AreaDeviceConfigWrapper configWrapper,
|
||||
Integer buttonId) {
|
||||
Long deviceId = configWrapper.getDeviceId();
|
||||
|
||||
log.info("[ButtonEvent] 查询键按下:deviceId={}, buttonId={}", deviceId, buttonId);
|
||||
|
||||
// 1. 查询设备当前工单
|
||||
DeviceCurrentOrderRedisDAO.OrderCacheInfo currentOrderJson = deviceCurrentOrderRedisDAO.getCurrentOrder(deviceId);
|
||||
if (currentOrderJson == null) {
|
||||
log.info("[ButtonEvent] 设备无当前工单:deviceId={}", deviceId);
|
||||
// 发布查询结果事件(无工单)
|
||||
publishQueryEvent(configWrapper, null, buttonId, "当前无工单");
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 解析工单信息
|
||||
Long orderId = extractOrderIdFromJson(currentOrderJson.getOrderId().toString());
|
||||
if (orderId == null) {
|
||||
log.warn("[ButtonEvent] 工单ID解析失败:deviceId={}, json={}", deviceId, currentOrderJson);
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 发布查询事件
|
||||
publishQueryEvent(configWrapper, orderId, buttonId, "查询当前工单");
|
||||
|
||||
log.info("[ButtonEvent] 发布工单查询事件:deviceId={}, orderId={}", deviceId, orderId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布工单确认事件
|
||||
*/
|
||||
private void publishConfirmEvent(CleanOrderIntegrationConfigService.AreaDeviceConfigWrapper configWrapper,
|
||||
Long orderId, Integer buttonId) {
|
||||
try {
|
||||
Map<String, Object> event = new HashMap<>();
|
||||
event.put("eventId", UUID.randomUUID().toString());
|
||||
event.put("orderType", "CLEAN");
|
||||
event.put("orderId", orderId);
|
||||
event.put("deviceId", configWrapper.getDeviceId());
|
||||
event.put("deviceKey", configWrapper.getDeviceKey());
|
||||
event.put("areaId", configWrapper.getAreaId());
|
||||
event.put("triggerSource", "IOT_BUTTON_CONFIRM");
|
||||
event.put("buttonId", buttonId);
|
||||
|
||||
rocketMQTemplate.syncSend(
|
||||
CleanOrderTopics.ORDER_CONFIRM,
|
||||
MessageBuilder.withPayload(event).build()
|
||||
);
|
||||
|
||||
log.info("[ButtonEvent] 确认事件已发布:eventId={}, orderId={}, deviceId={}",
|
||||
event.get("eventId"), orderId, configWrapper.getDeviceId());
|
||||
} catch (Exception e) {
|
||||
log.error("[ButtonEvent] 发布确认事件失败:deviceId={}, orderId={}",
|
||||
configWrapper.getDeviceId(), orderId, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发布工单查询事件
|
||||
*/
|
||||
private void publishQueryEvent(CleanOrderIntegrationConfigService.AreaDeviceConfigWrapper configWrapper,
|
||||
Long orderId, Integer buttonId, String message) {
|
||||
try {
|
||||
Map<String, Object> event = new HashMap<>();
|
||||
event.put("eventId", UUID.randomUUID().toString());
|
||||
event.put("orderType", "CLEAN");
|
||||
event.put("orderId", orderId);
|
||||
event.put("deviceId", configWrapper.getDeviceId());
|
||||
event.put("deviceKey", configWrapper.getDeviceKey());
|
||||
event.put("areaId", configWrapper.getAreaId());
|
||||
event.put("triggerSource", "IOT_BUTTON_QUERY");
|
||||
event.put("buttonId", buttonId);
|
||||
event.put("message", message);
|
||||
|
||||
rocketMQTemplate.syncSend(
|
||||
CleanOrderTopics.ORDER_AUDIT, // 查询事件使用审计主题
|
||||
MessageBuilder.withPayload(event).build()
|
||||
);
|
||||
|
||||
log.info("[ButtonEvent] 查询事件已发布:eventId={}, orderId={}, deviceId={}, message={}",
|
||||
event.get("eventId"), orderId, configWrapper.getDeviceId(), message);
|
||||
} catch (Exception e) {
|
||||
log.error("[ButtonEvent] 发布查询事件失败:deviceId={}, orderId={}",
|
||||
configWrapper.getDeviceId(), orderId, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 JSON 字符串中提取工单ID
|
||||
* <p>
|
||||
* 简单实现,生产环境建议使用 Jackson 或 Gson
|
||||
*/
|
||||
private Long extractOrderIdFromJson(String json) {
|
||||
try {
|
||||
// 简单解析:查找 "orderId":12345
|
||||
int orderIdIndex = json.indexOf("\"orderId\"");
|
||||
if (orderIdIndex == -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int colonIndex = json.indexOf(":", orderIdIndex);
|
||||
if (colonIndex == -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int endIndex = json.indexOf(",", colonIndex);
|
||||
if (endIndex == -1) {
|
||||
endIndex = json.indexOf("}", colonIndex);
|
||||
}
|
||||
|
||||
if (endIndex == -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String idStr = json.substring(colonIndex + 1, endIndex).trim();
|
||||
return Long.parseLong(idStr);
|
||||
} catch (Exception e) {
|
||||
log.error("[ButtonEvent] 解析工单ID失败:json={}", json, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置包装器
|
||||
*/
|
||||
private CleanOrderIntegrationConfigService.AreaDeviceConfigWrapper getConfigWrapper(Long deviceId) {
|
||||
return configService.getConfigWrapperByDeviceId(deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析按键ID
|
||||
*/
|
||||
private Integer parseButtonId(Object value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (value instanceof Number) {
|
||||
return ((Number) value).intValue();
|
||||
}
|
||||
|
||||
if (value instanceof String) {
|
||||
try {
|
||||
return Integer.parseInt((String) value);
|
||||
} catch (NumberFormatException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Resource
|
||||
private StringRedisTemplate stringRedisTemplate;
|
||||
}
|
||||
Reference in New Issue
Block a user