修改了红绿灯消息解析,使用原始格式
This commit is contained in:
parent
51ac84eb4f
commit
a3d8daa9d1
@ -1,20 +1,33 @@
|
||||
- 红绿灯状态上报消息格式:
|
||||
## 红绿灯数据格式说明
|
||||
|
||||
```
|
||||
('36.113.38.178', 56930) - {"DI-01":0,"DI-02":0,"DI-11":1,"DI-12":0,"DI-13":0,"DI-14":0,"DI-15":0,"DI-16":1,"DI-17":0,"DI-18":0}{
|
||||
"rw_prot": {
|
||||
"dir": "up",
|
||||
"Ver": "",
|
||||
"err": "1"
|
||||
}
|
||||
### 真实的红绿灯设备上报格式
|
||||
|
||||
红绿灯设备通过TCP连接发送的原始数据格式为纯JSON:
|
||||
|
||||
```json
|
||||
{"DI-01":0,"DI-02":0,"DI-11":1,"DI-12":0,"DI-13":0,"DI-14":0,"DI-15":0,"DI-16":1,"DI-17":0,"DI-18":0}
|
||||
```
|
||||
|
||||
- 其中:DI-11~13 表示南北向灯的状态,DI14~16 表示东西向灯
|
||||
### 数据字段说明
|
||||
|
||||
DI-11":北红,"DI-12":北黄,"DI-13":北绿,"DI-14":东红,"DI-15":东黄,"DI-16":东绿
|
||||
- **DI-11~13**: 南北向灯的状态
|
||||
- `DI-11`: 北红灯 (1=亮, 0=灭)
|
||||
- `DI-12`: 北黄灯 (1=亮, 0=灭)
|
||||
- `DI-13`: 北绿灯 (1=亮, 0=灭)
|
||||
|
||||
- 只有包含 DI 的这一段有用,其他的都是 0
|
||||
- **DI-14~16**: 东西向灯的状态
|
||||
- `DI-14`: 东红灯 (1=亮, 0=灭)
|
||||
- `DI-15`: 东黄灯 (1=亮, 0=灭)
|
||||
- `DI-16`: 东绿灯 (1=亮, 0=灭)
|
||||
|
||||
- 红绿灯状态上报频率:每 1 秒上报一次
|
||||
- **其他DI字段**: 通常为0,可忽略
|
||||
|
||||
- 红绿灯状态上报端口:8082
|
||||
### 网络连接信息
|
||||
|
||||
- **IP地址和端口**: 从TCP socket连接中获取,不包含在JSON数据中
|
||||
- **上报频率**: 每1秒上报一次
|
||||
- **监听端口**: 8082
|
||||
|
||||
### 注意事项
|
||||
|
||||
之前文档中的格式 `('36.113.38.178', 56930) - {...}` 实际上是服务器日志输出格式,不是设备的原始数据格式。真实的设备只发送JSON数据,IP地址和端口信息需要从socket连接中提取。
|
||||
|
||||
@ -12,8 +12,14 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
/**
|
||||
* 红绿灯信号解析器
|
||||
*
|
||||
* 负责解析DI格式的红绿灯信号JSON数据,转换为内部的TrafficLightStatus对象
|
||||
* 支持多种异常情况的处理,确保系统稳定性
|
||||
* 负责解析红绿灯设备发送的纯JSON格式DI信号数据,结合从socket连接中获取的IP地址和端口信息,
|
||||
* 转换为内部的TrafficLightStatus对象。支持多种异常情况的处理,确保系统稳定性。
|
||||
*
|
||||
* 数据格式说明:
|
||||
* - 红绿灯设备发送纯JSON: {"DI-01":0,"DI-11":1,"DI-12":0,...}
|
||||
* - IP地址和端口从TCP socket连接中获取,不包含在JSON数据中
|
||||
* - DI-11~13: 南北向灯状态 (红/黄/绿)
|
||||
* - DI-14~16: 东西向灯状态 (红/黄/绿)
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@ -32,37 +38,44 @@ public class TrafficLightSignalParser {
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析包含IP地址和端口信息的原始信号为TrafficLightStatus对象
|
||||
* 支持格式: ('IP地址', 端口) - {"DI-01":0,"DI-02":0,"DI-11":1,...}
|
||||
* 解析红绿灯JSON信号并结合连接信息创建TrafficLightStatus对象
|
||||
*
|
||||
* @param rawMessage 原始信号字符串
|
||||
* @param jsonSignal 纯JSON信号字符串,如: {"DI-01":0,"DI-11":1,"DI-12":0,...}
|
||||
* @param ipAddress 从socket连接中获取的IP地址
|
||||
* @param port 从socket连接中获取的端口号
|
||||
* @return 解析后的红绿灯状态,解析失败时返回安全默认状态
|
||||
*/
|
||||
public TrafficLightStatus parseSignalWithAddress(String rawMessage) {
|
||||
public TrafficLightStatus parseSignalWithAddress(String jsonSignal, String ipAddress, Integer port) {
|
||||
totalParsed.incrementAndGet();
|
||||
|
||||
if (!isValidMessageFormat(rawMessage)) {
|
||||
log.warn("🚦 无效的红绿灯消息格式: {}", rawMessage);
|
||||
if (!isValidSignal(jsonSignal)) {
|
||||
log.warn("🚦 无效的红绿灯JSON信号格式: {}", jsonSignal);
|
||||
failedParsed.incrementAndGet();
|
||||
return TrafficLightStatus.createSafeDefault(generateDeviceIdentifier(ipAddress, port));
|
||||
}
|
||||
|
||||
if (ipAddress == null || ipAddress.trim().isEmpty()) {
|
||||
log.warn("🚦 IP地址不能为空");
|
||||
failedParsed.incrementAndGet();
|
||||
return TrafficLightStatus.createSafeDefault("UNKNOWN_DEVICE");
|
||||
}
|
||||
|
||||
// 验证IP地址格式
|
||||
if (!isValidIpAddressFormat(ipAddress.trim())) {
|
||||
log.warn("🚦 IP地址格式无效: {}", ipAddress);
|
||||
failedParsed.incrementAndGet();
|
||||
return TrafficLightStatus.createSafeDefault(generateDeviceIdentifier(ipAddress, port));
|
||||
}
|
||||
|
||||
if (port == null || port <= 0 || port > 65535) {
|
||||
log.warn("🚦 端口号无效: {}", port);
|
||||
failedParsed.incrementAndGet();
|
||||
return TrafficLightStatus.createSafeDefault(generateDeviceIdentifier(ipAddress, port));
|
||||
}
|
||||
|
||||
try {
|
||||
// 提取IP地址和端口信息
|
||||
String ipAddress = extractIpAddress(rawMessage);
|
||||
Integer port = extractPort(rawMessage);
|
||||
|
||||
// 提取DI信号数据
|
||||
String diData = extractDiData(rawMessage);
|
||||
|
||||
if (ipAddress == null || port == null || diData == null) {
|
||||
log.warn("🚦 无法提取完整的地址信息或DI数据: {}", rawMessage);
|
||||
failedParsed.incrementAndGet();
|
||||
return TrafficLightStatus.createSafeDefault("UNKNOWN_DEVICE");
|
||||
}
|
||||
|
||||
// 解析DI信号数据
|
||||
JsonNode rootNode = objectMapper.readTree(diData);
|
||||
// 解析JSON数据
|
||||
JsonNode rootNode = objectMapper.readTree(jsonSignal);
|
||||
|
||||
// 解析南北方向信号状态 (DI-11: 北红, DI-12: 北黄, DI-13: 北绿)
|
||||
SignalState nsStatus = parseDirectionSignal(rootNode, "DI-11", "DI-12", "DI-13");
|
||||
@ -71,17 +84,17 @@ public class TrafficLightSignalParser {
|
||||
SignalState ewStatus = parseDirectionSignal(rootNode, "DI-14", "DI-15", "DI-16");
|
||||
|
||||
// 生成设备标识符(使用IP:端口组合)
|
||||
String deviceIdentifier = ipAddress + ":" + port;
|
||||
String deviceIdentifier = generateDeviceIdentifier(ipAddress, port);
|
||||
|
||||
// 创建状态对象
|
||||
TrafficLightStatus status = TrafficLightStatus.builder()
|
||||
.deviceId(null) // 设备ID可能为空,使用IP:端口作为标识
|
||||
.ipAddress(ipAddress)
|
||||
.ipAddress(ipAddress.trim())
|
||||
.port(port)
|
||||
.nsStatus(nsStatus)
|
||||
.ewStatus(ewStatus)
|
||||
.timestamp(System.currentTimeMillis() * 1000) // 微秒级时间戳
|
||||
.rawSignal(rawMessage)
|
||||
.rawSignal(jsonSignal)
|
||||
.build();
|
||||
|
||||
// 验证解析结果
|
||||
@ -107,9 +120,10 @@ public class TrafficLightSignalParser {
|
||||
return status;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("🚦 解析红绿灯信号异常: {}", rawMessage, e);
|
||||
log.error("🚦 解析红绿灯信号异常: jsonSignal={}, ipAddress={}, port={}",
|
||||
jsonSignal, ipAddress, port, e);
|
||||
failedParsed.incrementAndGet();
|
||||
return TrafficLightStatus.createSafeDefault("UNKNOWN_DEVICE");
|
||||
return TrafficLightStatus.createSafeDefault(generateDeviceIdentifier(ipAddress, port));
|
||||
}
|
||||
}
|
||||
|
||||
@ -183,122 +197,49 @@ public class TrafficLightSignalParser {
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证新消息格式是否有效
|
||||
* 格式: ('IP地址', 端口) - {"DI-01":0,"DI-02":0,"DI-11":1,...}
|
||||
* 验证IP地址格式是否有效
|
||||
*
|
||||
* @param rawMessage 原始消息字符串
|
||||
* @param ipAddress IP地址字符串
|
||||
* @return true如果格式有效,false否则
|
||||
*/
|
||||
public boolean isValidMessageFormat(String rawMessage) {
|
||||
if (rawMessage == null || rawMessage.trim().isEmpty()) {
|
||||
private boolean isValidIpAddressFormat(String ipAddress) {
|
||||
if (ipAddress == null || ipAddress.trim().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// 检查是否包含IP地址和端口的格式
|
||||
if (!rawMessage.contains("(") || !rawMessage.contains(")") || !rawMessage.contains("-")) {
|
||||
String[] parts = ipAddress.split("\\.");
|
||||
if (parts.length != 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 尝试提取各部分
|
||||
String ipAddress = extractIpAddress(rawMessage);
|
||||
Integer port = extractPort(rawMessage);
|
||||
String diData = extractDiData(rawMessage);
|
||||
|
||||
if (ipAddress == null || port == null || diData == null) {
|
||||
return false;
|
||||
for (String part : parts) {
|
||||
int num = Integer.parseInt(part);
|
||||
if (num < 0 || num > 255) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 验证DI数据是否为有效JSON
|
||||
JsonNode rootNode = objectMapper.readTree(diData);
|
||||
if (!rootNode.isObject()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查是否包含必要的DI字段
|
||||
boolean hasRequiredFields = rootNode.has("DI-11") || rootNode.has("DI-12") || rootNode.has("DI-13") ||
|
||||
rootNode.has("DI-14") || rootNode.has("DI-15") || rootNode.has("DI-16");
|
||||
|
||||
return hasRequiredFields;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.debug("消息格式验证失败: {}", rawMessage, e);
|
||||
return true;
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从原始消息中提取IP地址
|
||||
* 生成设备标识符
|
||||
*
|
||||
* @param rawMessage 原始消息字符串
|
||||
* @return IP地址,提取失败时返回null
|
||||
* @param ipAddress IP地址
|
||||
* @param port 端口号
|
||||
* @return 设备标识符,格式为 "IP:端口"
|
||||
*/
|
||||
private String extractIpAddress(String rawMessage) {
|
||||
try {
|
||||
// 使用正则表达式匹配 ('IP地址', 端口) 格式
|
||||
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("\\('([^']+)',\\s*(\\d+)\\)");
|
||||
java.util.regex.Matcher matcher = pattern.matcher(rawMessage);
|
||||
|
||||
if (matcher.find()) {
|
||||
return matcher.group(1);
|
||||
}
|
||||
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
log.debug("提取IP地址失败: {}", rawMessage, e);
|
||||
return null;
|
||||
private String generateDeviceIdentifier(String ipAddress, Integer port) {
|
||||
if (ipAddress == null || ipAddress.trim().isEmpty()) {
|
||||
return "UNKNOWN_DEVICE";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从原始消息中提取端口号
|
||||
*
|
||||
* @param rawMessage 原始消息字符串
|
||||
* @return 端口号,提取失败时返回null
|
||||
*/
|
||||
private Integer extractPort(String rawMessage) {
|
||||
try {
|
||||
// 使用正则表达式匹配 ('IP地址', 端口) 格式
|
||||
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("\\('([^']+)',\\s*(\\d+)\\)");
|
||||
java.util.regex.Matcher matcher = pattern.matcher(rawMessage);
|
||||
|
||||
if (matcher.find()) {
|
||||
return Integer.parseInt(matcher.group(2));
|
||||
}
|
||||
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
log.debug("提取端口号失败: {}", rawMessage, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从原始消息中提取DI信号数据
|
||||
*
|
||||
* @param rawMessage 原始消息字符串
|
||||
* @return DI信号JSON字符串,提取失败时返回null
|
||||
*/
|
||||
private String extractDiData(String rawMessage) {
|
||||
try {
|
||||
// 查找 " - " 分隔符后的JSON数据
|
||||
int separatorIndex = rawMessage.indexOf(" - ");
|
||||
if (separatorIndex == -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String jsonPart = rawMessage.substring(separatorIndex + 3).trim();
|
||||
|
||||
// 验证是否为有效的JSON格式
|
||||
if (jsonPart.startsWith("{") && jsonPart.endsWith("}")) {
|
||||
return jsonPart;
|
||||
}
|
||||
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
log.debug("提取DI数据失败: {}", rawMessage, e);
|
||||
return null;
|
||||
if (port == null) {
|
||||
return ipAddress.trim();
|
||||
}
|
||||
return ipAddress.trim() + ":" + port;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -483,6 +483,82 @@ public class DataProcessingService {
|
||||
@Autowired
|
||||
private IntersectionService intersectionService;
|
||||
|
||||
/**
|
||||
* 处理红绿灯信号数据(新格式:分离的JSON数据和网络连接信息)
|
||||
*
|
||||
* @param jsonSignal 纯JSON信号数据
|
||||
* @param ipAddress 从socket连接中获取的IP地址
|
||||
* @param port 从socket连接中获取的端口号
|
||||
*/
|
||||
public void processTrafficLightSignalWithAddress(String jsonSignal, String ipAddress, Integer port) {
|
||||
if (jsonSignal == null || jsonSignal.trim().isEmpty()) {
|
||||
log.warn("🚦 接收到空的红绿灯JSON信号");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ipAddress == null || ipAddress.trim().isEmpty()) {
|
||||
log.warn("🚦 IP地址不能为空");
|
||||
return;
|
||||
}
|
||||
|
||||
if (port == null || port <= 0 || port > 65535) {
|
||||
log.warn("🚦 端口号无效: {}", port);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 使用新的解析器处理分离的JSON数据和网络信息
|
||||
com.qaup.collision.dataprocessing.model.TrafficLightStatus status =
|
||||
trafficLightSignalParser.parseSignalWithAddress(jsonSignal, ipAddress, port);
|
||||
|
||||
log.debug("🚦 使用分离格式解析器处理信号: ipAddress={}, port={}, json={}",
|
||||
ipAddress, port, jsonSignal.substring(0, Math.min(100, jsonSignal.length())));
|
||||
|
||||
if (!status.isValid()) {
|
||||
log.warn("🚦 解析的红绿灯状态无效: {}", status);
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取或创建设备
|
||||
com.qaup.collision.common.model.spatial.TrafficLight device = getOrCreateDevice(status);
|
||||
if (device == null) {
|
||||
log.warn("🚦 无法获取或创建红绿灯设备");
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新设备心跳和在线状态
|
||||
updateDeviceStatusByAddress(status, device);
|
||||
|
||||
// 设置路口ID
|
||||
status.setIntersectionId(device.getIntersectionId());
|
||||
|
||||
// 获取路口信息
|
||||
Optional<com.qaup.collision.common.model.spatial.Intersection> intersectionOpt =
|
||||
intersectionService.getActiveIntersectionById(device.getIntersectionId());
|
||||
|
||||
if (intersectionOpt.isEmpty()) {
|
||||
log.warn("🚦 无法获取路口信息: intersectionId={}", device.getIntersectionId());
|
||||
return;
|
||||
}
|
||||
|
||||
com.qaup.collision.common.model.spatial.Intersection intersection = intersectionOpt.get();
|
||||
|
||||
// 创建WebSocket消息载荷
|
||||
com.qaup.collision.websocket.message.TrafficLightStatusPayload payload =
|
||||
createTrafficLightPayload(status, device, intersection);
|
||||
|
||||
// 发布红绿灯状态变更事件
|
||||
publishTrafficLightStatusEvent(payload);
|
||||
|
||||
log.debug("🚦 成功处理红绿灯信号: deviceIdentifier={}, intersectionId={}, 状态={}",
|
||||
status.generateDeviceIdentifier(), status.getIntersectionId(), status.getStatusDescription());
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("🚦 处理红绿灯信号异常: ipAddress={}, port={}, json={}",
|
||||
ipAddress, port, jsonSignal.substring(0, Math.min(100, jsonSignal.length())), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理红绿灯信号数据(支持包含IP地址和端口信息的新格式)
|
||||
*
|
||||
@ -497,13 +573,9 @@ public class DataProcessingService {
|
||||
try {
|
||||
com.qaup.collision.dataprocessing.model.TrafficLightStatus status;
|
||||
|
||||
// 检查消息格式,优先使用新的IP地址格式解析器
|
||||
if (trafficLightSignalParser.isValidMessageFormat(rawMessage)) {
|
||||
// 使用新的解析器处理包含IP地址和端口信息的消息
|
||||
status = trafficLightSignalParser.parseSignalWithAddress(rawMessage);
|
||||
log.debug("🚦 使用IP地址格式解析器处理信号: {}", rawMessage.substring(0, Math.min(100, rawMessage.length())));
|
||||
} else if (trafficLightSignalParser.isValidSignal(rawMessage)) {
|
||||
// 使用旧的解析器处理传统JSON格式消息(向后兼容)
|
||||
// 只支持传统JSON格式(向后兼容)
|
||||
if (trafficLightSignalParser.isValidSignal(rawMessage)) {
|
||||
// 使用传统JSON格式解析器处理信号(向后兼容)
|
||||
status = trafficLightSignalParser.parseSignal(rawMessage);
|
||||
log.debug("🚦 使用传统JSON格式解析器处理信号");
|
||||
} else {
|
||||
|
||||
@ -9,7 +9,8 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
/**
|
||||
* TrafficLightSignalParser增强功能测试类
|
||||
*
|
||||
* 测试新增的IP地址和端口解析功能
|
||||
* 测试基于纯JSON格式和socket连接信息的解析功能
|
||||
* 新的数据格式:红绿灯设备发送纯JSON,IP地址和端口从socket连接中获取
|
||||
*/
|
||||
class TrafficLightSignalParserEnhancedTest {
|
||||
|
||||
@ -22,10 +23,12 @@ class TrafficLightSignalParserEnhancedTest {
|
||||
|
||||
@Test
|
||||
void testParseSignalWithAddress_ValidMessage() {
|
||||
// 测试有效的消息格式
|
||||
String rawMessage = "('36.113.38.178', 56930) - {\"DI-01\":0,\"DI-02\":0,\"DI-11\":1,\"DI-12\":0,\"DI-13\":0,\"DI-14\":0,\"DI-15\":0,\"DI-16\":1,\"DI-17\":0,\"DI-18\":0}";
|
||||
// 测试有效的纯JSON格式和连接信息
|
||||
String jsonSignal = "{\"DI-01\":0,\"DI-02\":0,\"DI-11\":1,\"DI-12\":0,\"DI-13\":0,\"DI-14\":0,\"DI-15\":0,\"DI-16\":1,\"DI-17\":0,\"DI-18\":0}";
|
||||
String ipAddress = "36.113.38.178";
|
||||
Integer port = 56930;
|
||||
|
||||
TrafficLightStatus status = parser.parseSignalWithAddress(rawMessage);
|
||||
TrafficLightStatus status = parser.parseSignalWithAddress(jsonSignal, ipAddress, port);
|
||||
|
||||
assertNotNull(status);
|
||||
assertTrue(status.isValid());
|
||||
@ -33,15 +36,16 @@ class TrafficLightSignalParserEnhancedTest {
|
||||
assertEquals(Integer.valueOf(56930), status.getPort());
|
||||
assertEquals(SignalState.RED, status.getNsStatus()); // DI-11=1 表示北红
|
||||
assertEquals(SignalState.GREEN, status.getEwStatus()); // DI-16=1 表示东绿
|
||||
assertEquals("36.113.38.178:56930", status.generateDeviceIdentifier());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseSignalWithAddress_DifferentStates() {
|
||||
// 测试不同的信号状态组合
|
||||
String rawMessage = "('192.168.1.100', 8082) - {\"DI-11\":0,\"DI-12\":1,\"DI-13\":0,\"DI-14\":1,\"DI-15\":0,\"DI-16\":0}";
|
||||
String jsonSignal = "{\"DI-11\":0,\"DI-12\":1,\"DI-13\":0,\"DI-14\":1,\"DI-15\":0,\"DI-16\":0}";
|
||||
String ipAddress = "192.168.1.100";
|
||||
Integer port = 8082;
|
||||
|
||||
TrafficLightStatus status = parser.parseSignalWithAddress(rawMessage);
|
||||
TrafficLightStatus status = parser.parseSignalWithAddress(jsonSignal, ipAddress, port);
|
||||
|
||||
assertNotNull(status);
|
||||
assertTrue(status.isValid());
|
||||
@ -54,30 +58,35 @@ class TrafficLightSignalParserEnhancedTest {
|
||||
@Test
|
||||
void testParseSignalWithAddress_AllGreenConflict() {
|
||||
// 测试冲突状态(两个方向都是绿灯)
|
||||
String rawMessage = "('10.0.0.1', 9090) - {\"DI-11\":0,\"DI-12\":0,\"DI-13\":1,\"DI-14\":0,\"DI-15\":0,\"DI-16\":1}";
|
||||
String jsonSignal = "{\"DI-11\":0,\"DI-12\":0,\"DI-13\":1,\"DI-14\":0,\"DI-15\":0,\"DI-16\":1}";
|
||||
String ipAddress = "10.0.0.1";
|
||||
Integer port = 9090;
|
||||
|
||||
TrafficLightStatus status = parser.parseSignalWithAddress(rawMessage);
|
||||
TrafficLightStatus status = parser.parseSignalWithAddress(jsonSignal, ipAddress, port);
|
||||
|
||||
assertNotNull(status);
|
||||
// 冲突时应该返回安全状态(红灯)
|
||||
assertEquals(SignalState.RED, status.getNsStatus());
|
||||
assertEquals(SignalState.RED, status.getEwStatus());
|
||||
assertEquals("10.0.0.1:9090", status.generateDeviceIdentifier());
|
||||
assertEquals("10.0.0.1", status.getIpAddress());
|
||||
assertEquals(Integer.valueOf(9090), status.getPort());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseSignalWithAddress_InvalidFormat() {
|
||||
// 测试无效的消息格式
|
||||
String[] invalidMessages = {
|
||||
"invalid message",
|
||||
"('192.168.1.1') - {\"DI-11\":1}", // 缺少端口
|
||||
"192.168.1.1, 8082 - {\"DI-11\":1}", // 格式错误
|
||||
"('192.168.1.1', 8082)", // 缺少DI数据
|
||||
"('192.168.1.1', 8082) - invalid_json"
|
||||
// 测试无效的JSON格式和连接信息
|
||||
String[] invalidJsons = {
|
||||
"invalid json",
|
||||
"{\"invalid\":\"data\"}",
|
||||
"not json at all",
|
||||
"{\"DI-11\":\"invalid_value\"}"
|
||||
};
|
||||
|
||||
for (String invalidMessage : invalidMessages) {
|
||||
TrafficLightStatus status = parser.parseSignalWithAddress(invalidMessage);
|
||||
String validIp = "192.168.1.1";
|
||||
Integer validPort = 8082;
|
||||
|
||||
for (String invalidJson : invalidJsons) {
|
||||
TrafficLightStatus status = parser.parseSignalWithAddress(invalidJson, validIp, validPort);
|
||||
assertNotNull(status);
|
||||
// 无效格式应该返回安全默认状态
|
||||
assertEquals(SignalState.RED, status.getNsStatus());
|
||||
@ -86,50 +95,53 @@ class TrafficLightSignalParserEnhancedTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExtractIpAddress() {
|
||||
// 通过反射测试私有方法(或者通过公共方法间接测试)
|
||||
String rawMessage = "('172.16.0.1', 8083) - {\"DI-11\":1}";
|
||||
void testParseSignalWithAddress_InvalidIpAddress() {
|
||||
// 测试无效的IP地址
|
||||
String validJson = "{\"DI-11\":1,\"DI-12\":0,\"DI-13\":0,\"DI-14\":0,\"DI-15\":0,\"DI-16\":1}";
|
||||
|
||||
TrafficLightStatus status = parser.parseSignalWithAddress(rawMessage);
|
||||
String[] invalidIps = {null, "", " ", "invalid.ip"};
|
||||
Integer validPort = 8082;
|
||||
|
||||
assertEquals("172.16.0.1", status.getIpAddress());
|
||||
for (String invalidIp : invalidIps) {
|
||||
TrafficLightStatus status = parser.parseSignalWithAddress(validJson, invalidIp, validPort);
|
||||
assertNotNull(status);
|
||||
assertEquals(SignalState.RED, status.getNsStatus());
|
||||
assertEquals(SignalState.RED, status.getEwStatus());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExtractPort() {
|
||||
// 测试端口提取
|
||||
String rawMessage = "('192.168.1.1', 9999) - {\"DI-11\":1}";
|
||||
void testParseSignalWithAddress_InvalidPort() {
|
||||
// 测试无效的端口号
|
||||
String validJson = "{\"DI-11\":1,\"DI-12\":0,\"DI-13\":0,\"DI-14\":0,\"DI-15\":0,\"DI-16\":1}";
|
||||
String validIp = "192.168.1.1";
|
||||
|
||||
TrafficLightStatus status = parser.parseSignalWithAddress(rawMessage);
|
||||
Integer[] invalidPorts = {null, -1, 0, 65536, 99999};
|
||||
|
||||
assertEquals(Integer.valueOf(9999), status.getPort());
|
||||
for (Integer invalidPort : invalidPorts) {
|
||||
TrafficLightStatus status = parser.parseSignalWithAddress(validJson, validIp, invalidPort);
|
||||
assertNotNull(status);
|
||||
assertEquals(SignalState.RED, status.getNsStatus());
|
||||
assertEquals(SignalState.RED, status.getEwStatus());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExtractDiData() {
|
||||
// 测试DI数据提取
|
||||
String rawMessage = "('192.168.1.1', 8082) - {\"DI-11\":1,\"DI-12\":0,\"DI-13\":0,\"DI-14\":0,\"DI-15\":1,\"DI-16\":0}";
|
||||
void testParseSignalWithAddress_ComplexDiData() {
|
||||
// 测试复杂的DI数据解析
|
||||
String jsonSignal = "{\"DI-11\":1,\"DI-12\":0,\"DI-13\":0,\"DI-14\":0,\"DI-15\":1,\"DI-16\":0}";
|
||||
String ipAddress = "172.16.0.1";
|
||||
Integer port = 8083;
|
||||
|
||||
TrafficLightStatus status = parser.parseSignalWithAddress(rawMessage);
|
||||
TrafficLightStatus status = parser.parseSignalWithAddress(jsonSignal, ipAddress, port);
|
||||
|
||||
assertNotNull(status);
|
||||
assertEquals("172.16.0.1", status.getIpAddress());
|
||||
assertEquals(Integer.valueOf(8083), status.getPort());
|
||||
assertEquals(SignalState.RED, status.getNsStatus()); // DI-11=1
|
||||
assertEquals(SignalState.YELLOW, status.getEwStatus()); // DI-15=1
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIsValidMessageFormat() {
|
||||
// 测试消息格式验证
|
||||
assertTrue(parser.isValidMessageFormat("('192.168.1.1', 8082) - {\"DI-11\":1}"));
|
||||
assertTrue(parser.isValidMessageFormat("('36.113.38.178', 56930) - {\"DI-01\":0,\"DI-11\":1,\"DI-16\":1}"));
|
||||
|
||||
assertFalse(parser.isValidMessageFormat(null));
|
||||
assertFalse(parser.isValidMessageFormat(""));
|
||||
assertFalse(parser.isValidMessageFormat("invalid"));
|
||||
assertFalse(parser.isValidMessageFormat("('192.168.1.1', 8082)")); // 缺少DI数据
|
||||
assertFalse(parser.isValidMessageFormat("192.168.1.1 - {\"DI-11\":1}")); // 缺少括号格式
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBackwardCompatibility() {
|
||||
// 测试向后兼容性 - 旧的parseSignal方法仍然工作
|
||||
@ -146,7 +158,7 @@ class TrafficLightSignalParserEnhancedTest {
|
||||
|
||||
@Test
|
||||
void testTrafficLightStatusWithIpPort() {
|
||||
// 测试TrafficLightStatus的新功能
|
||||
// 测试TrafficLightStatus的IP端口功能
|
||||
TrafficLightStatus status = TrafficLightStatus.builder()
|
||||
.ipAddress("192.168.1.100")
|
||||
.port(8082)
|
||||
@ -156,32 +168,17 @@ class TrafficLightSignalParserEnhancedTest {
|
||||
.build();
|
||||
|
||||
assertTrue(status.isValid());
|
||||
assertEquals("192.168.1.100:8082", status.generateDeviceIdentifier());
|
||||
assertEquals("192.168.1.100", status.getIpAddress());
|
||||
assertEquals(Integer.valueOf(8082), status.getPort());
|
||||
assertNull(status.getDeviceId()); // 设备ID为空
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateSafeDefaultWithIpPort() {
|
||||
// 测试使用IP:端口格式创建安全默认状态
|
||||
TrafficLightStatus status = TrafficLightStatus.createSafeDefault("10.0.0.1:8080");
|
||||
|
||||
assertNotNull(status);
|
||||
assertEquals("10.0.0.1", status.getIpAddress());
|
||||
assertEquals(Integer.valueOf(8080), status.getPort());
|
||||
assertEquals(SignalState.RED, status.getNsStatus());
|
||||
assertEquals(SignalState.RED, status.getEwStatus());
|
||||
assertNull(status.getDeviceId());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateSafeDefaultWithDeviceId() {
|
||||
// 测试使用设备ID创建安全默认状态
|
||||
TrafficLightStatus status = TrafficLightStatus.createSafeDefault("TL_001");
|
||||
|
||||
assertNotNull(status);
|
||||
assertEquals("TL_001", status.getDeviceId());
|
||||
assertNull(status.getIpAddress());
|
||||
assertNull(status.getPort());
|
||||
assertEquals(SignalState.RED, status.getNsStatus());
|
||||
assertEquals(SignalState.RED, status.getEwStatus());
|
||||
}
|
||||
@ -192,9 +189,9 @@ class TrafficLightSignalParserEnhancedTest {
|
||||
parser.resetStatistics();
|
||||
|
||||
// 解析一些消息
|
||||
parser.parseSignalWithAddress("('192.168.1.1', 8082) - {\"DI-11\":1}");
|
||||
parser.parseSignalWithAddress("invalid message");
|
||||
parser.parseSignalWithAddress("('192.168.1.2', 8083) - {\"DI-14\":1}");
|
||||
parser.parseSignalWithAddress("{\"DI-11\":1}", "192.168.1.1", 8082);
|
||||
parser.parseSignalWithAddress("invalid json", "192.168.1.1", 8082);
|
||||
parser.parseSignalWithAddress("{\"DI-14\":1}", "192.168.1.2", 8083);
|
||||
|
||||
TrafficLightSignalParser.ParseStatistics stats = parser.getStatistics();
|
||||
|
||||
|
||||
@ -28,26 +28,26 @@ import static org.mockito.Mockito.*;
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class DataProcessingServiceTrafficLightTest {
|
||||
|
||||
|
||||
@Mock
|
||||
private TrafficLightSignalParser trafficLightSignalParser;
|
||||
|
||||
|
||||
@Mock
|
||||
private TrafficLightService trafficLightService;
|
||||
|
||||
|
||||
@Mock
|
||||
private IntersectionService intersectionService;
|
||||
|
||||
|
||||
@Mock
|
||||
private ApplicationEventPublisher eventPublisher;
|
||||
|
||||
|
||||
@InjectMocks
|
||||
private DataProcessingService dataProcessingService;
|
||||
|
||||
|
||||
private TrafficLight testDevice;
|
||||
private Intersection testIntersection;
|
||||
private TrafficLightStatus testStatus;
|
||||
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
testDevice = TrafficLight.builder()
|
||||
@ -61,7 +61,7 @@ class DataProcessingServiceTrafficLightTest {
|
||||
.isActive(true)
|
||||
.isOnline(false)
|
||||
.build();
|
||||
|
||||
|
||||
testIntersection = Intersection.builder()
|
||||
.id(1L)
|
||||
.intersectionId("INTERSECTION_001")
|
||||
@ -71,7 +71,7 @@ class DataProcessingServiceTrafficLightTest {
|
||||
.areaCode("AREA_A")
|
||||
.isActive(true)
|
||||
.build();
|
||||
|
||||
|
||||
testStatus = TrafficLightStatus.builder()
|
||||
.deviceId("TL_001")
|
||||
.ipAddress("192.168.1.100")
|
||||
@ -82,46 +82,46 @@ class DataProcessingServiceTrafficLightTest {
|
||||
.rawSignal("('192.168.1.100', 8082) - {\"DI-11\":1,\"DI-16\":1}")
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testProcessTrafficLightSignal_WithIpAddressFormat() {
|
||||
// 测试处理包含IP地址和端口信息的新格式消息
|
||||
String rawMessage = "('192.168.1.100', 8082) - {\"DI-11\":1,\"DI-12\":0,\"DI-13\":0,\"DI-14\":0,\"DI-15\":0,\"DI-16\":1}";
|
||||
|
||||
// 测试处理纯JSON格式和网络连接信息
|
||||
String jsonSignal = "{\"DI-11\":1,\"DI-12\":0,\"DI-13\":0,\"DI-14\":0,\"DI-15\":0,\"DI-16\":1}";
|
||||
String ipAddress = "192.168.1.100";
|
||||
Integer port = 8082;
|
||||
|
||||
// Mock解析器行为
|
||||
when(trafficLightSignalParser.isValidMessageFormat(rawMessage)).thenReturn(true);
|
||||
when(trafficLightSignalParser.parseSignalWithAddress(rawMessage)).thenReturn(testStatus);
|
||||
|
||||
when(trafficLightSignalParser.parseSignalWithAddress(jsonSignal, ipAddress, port)).thenReturn(testStatus);
|
||||
|
||||
// Mock设备查找
|
||||
when(trafficLightService.findDeviceByAddress("192.168.1.100", 8082))
|
||||
.thenReturn(Optional.of(testDevice));
|
||||
|
||||
|
||||
// Mock设备状态更新
|
||||
when(trafficLightService.updateDeviceHeartbeatByAddress("192.168.1.100", 8082)).thenReturn(true);
|
||||
when(trafficLightService.updateDeviceOnlineStatusByAddress("192.168.1.100", 8082, true)).thenReturn(true);
|
||||
|
||||
|
||||
// Mock路口查找
|
||||
when(intersectionService.getActiveIntersectionById("INTERSECTION_001"))
|
||||
.thenReturn(Optional.of(testIntersection));
|
||||
|
||||
// 执行测试
|
||||
dataProcessingService.processTrafficLightSignal(rawMessage);
|
||||
|
||||
|
||||
// 执行测试 - 模拟从网络层接收到JSON数据和连接信息
|
||||
dataProcessingService.processTrafficLightSignalWithAddress(jsonSignal, ipAddress, port);
|
||||
|
||||
// 验证调用
|
||||
verify(trafficLightSignalParser).isValidMessageFormat(rawMessage);
|
||||
verify(trafficLightSignalParser).parseSignalWithAddress(rawMessage);
|
||||
verify(trafficLightSignalParser).parseSignalWithAddress(jsonSignal, ipAddress, port);
|
||||
verify(trafficLightService).findDeviceByAddress("192.168.1.100", 8082);
|
||||
verify(trafficLightService).updateDeviceHeartbeatByAddress("192.168.1.100", 8082);
|
||||
verify(trafficLightService).updateDeviceOnlineStatusByAddress("192.168.1.100", 8082, true);
|
||||
verify(intersectionService).getActiveIntersectionById("INTERSECTION_001");
|
||||
verify(eventPublisher).publishEvent(any(TrafficLightStatusEvent.class));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testProcessTrafficLightSignal_WithTraditionalFormat() {
|
||||
// 测试处理传统JSON格式消息(向后兼容)
|
||||
String rawMessage = "{\"device_id\":\"TL_001\",\"DI-11\":1,\"DI-16\":1}";
|
||||
|
||||
|
||||
TrafficLightStatus traditionalStatus = TrafficLightStatus.builder()
|
||||
.deviceId("TL_001")
|
||||
.nsStatus(SignalState.RED)
|
||||
@ -129,29 +129,27 @@ class DataProcessingServiceTrafficLightTest {
|
||||
.timestamp(System.currentTimeMillis() * 1000)
|
||||
.rawSignal(rawMessage)
|
||||
.build();
|
||||
|
||||
|
||||
// Mock解析器行为
|
||||
when(trafficLightSignalParser.isValidMessageFormat(rawMessage)).thenReturn(false);
|
||||
when(trafficLightSignalParser.isValidSignal(rawMessage)).thenReturn(true);
|
||||
when(trafficLightSignalParser.parseSignal(rawMessage)).thenReturn(traditionalStatus);
|
||||
|
||||
|
||||
// Mock设备查找(通过设备ID)
|
||||
when(trafficLightService.getActiveTrafficLightByDeviceId("TL_001"))
|
||||
.thenReturn(Optional.of(testDevice));
|
||||
|
||||
|
||||
// Mock设备状态更新
|
||||
when(trafficLightService.updateDeviceHeartbeat("TL_001")).thenReturn(true);
|
||||
when(trafficLightService.updateDeviceOnlineStatus("TL_001", true)).thenReturn(true);
|
||||
|
||||
|
||||
// Mock路口查找
|
||||
when(intersectionService.getActiveIntersectionById("INTERSECTION_001"))
|
||||
.thenReturn(Optional.of(testIntersection));
|
||||
|
||||
|
||||
// 执行测试
|
||||
dataProcessingService.processTrafficLightSignal(rawMessage);
|
||||
|
||||
|
||||
// 验证调用
|
||||
verify(trafficLightSignalParser).isValidMessageFormat(rawMessage);
|
||||
verify(trafficLightSignalParser).isValidSignal(rawMessage);
|
||||
verify(trafficLightSignalParser).parseSignal(rawMessage);
|
||||
verify(trafficLightService).getActiveTrafficLightByDeviceId("TL_001");
|
||||
@ -159,21 +157,23 @@ class DataProcessingServiceTrafficLightTest {
|
||||
verify(trafficLightService).updateDeviceOnlineStatus("TL_001", true);
|
||||
verify(eventPublisher).publishEvent(any(TrafficLightStatusEvent.class));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testProcessTrafficLightSignal_AutoCreateDevice() {
|
||||
// 测试自动创建设备功能
|
||||
String rawMessage = "('10.0.0.1', 9090) - {\"DI-11\":1,\"DI-14\":1}";
|
||||
|
||||
String jsonSignal = "{\"DI-11\":1,\"DI-14\":1}";
|
||||
String ipAddress = "10.0.0.1";
|
||||
Integer port = 9090;
|
||||
|
||||
TrafficLightStatus newDeviceStatus = TrafficLightStatus.builder()
|
||||
.ipAddress("10.0.0.1")
|
||||
.port(9090)
|
||||
.nsStatus(SignalState.RED)
|
||||
.ewStatus(SignalState.RED)
|
||||
.timestamp(System.currentTimeMillis() * 1000)
|
||||
.rawSignal(rawMessage)
|
||||
.rawSignal(jsonSignal)
|
||||
.build();
|
||||
|
||||
|
||||
TrafficLight newDevice = TrafficLight.builder()
|
||||
.id(2L)
|
||||
.deviceName("TrafficLight_10_0_0_1_9090")
|
||||
@ -184,7 +184,7 @@ class DataProcessingServiceTrafficLightTest {
|
||||
.isActive(true)
|
||||
.isOnline(false)
|
||||
.build();
|
||||
|
||||
|
||||
Intersection defaultIntersection = Intersection.builder()
|
||||
.id(2L)
|
||||
.intersectionId("DEFAULT_INTERSECTION")
|
||||
@ -194,28 +194,27 @@ class DataProcessingServiceTrafficLightTest {
|
||||
.areaCode("DEFAULT")
|
||||
.isActive(true)
|
||||
.build();
|
||||
|
||||
|
||||
// Mock解析器行为
|
||||
when(trafficLightSignalParser.isValidMessageFormat(rawMessage)).thenReturn(true);
|
||||
when(trafficLightSignalParser.parseSignalWithAddress(rawMessage)).thenReturn(newDeviceStatus);
|
||||
|
||||
when(trafficLightSignalParser.parseSignalWithAddress(jsonSignal, ipAddress, port)).thenReturn(newDeviceStatus);
|
||||
|
||||
// Mock设备查找(不存在)和创建
|
||||
when(trafficLightService.findDeviceByAddress("10.0.0.1", 9090))
|
||||
.thenReturn(Optional.empty());
|
||||
when(trafficLightService.getOrCreateDeviceByAddress("10.0.0.1", 9090, "DEFAULT_INTERSECTION"))
|
||||
.thenReturn(newDevice);
|
||||
|
||||
|
||||
// Mock设备状态更新
|
||||
when(trafficLightService.updateDeviceHeartbeatByAddress("10.0.0.1", 9090)).thenReturn(true);
|
||||
when(trafficLightService.updateDeviceOnlineStatusByAddress("10.0.0.1", 9090, true)).thenReturn(true);
|
||||
|
||||
|
||||
// Mock路口查找
|
||||
when(intersectionService.getActiveIntersectionById("DEFAULT_INTERSECTION"))
|
||||
.thenReturn(Optional.of(defaultIntersection));
|
||||
|
||||
|
||||
// 执行测试
|
||||
dataProcessingService.processTrafficLightSignal(rawMessage);
|
||||
|
||||
dataProcessingService.processTrafficLightSignalWithAddress(jsonSignal, ipAddress, port);
|
||||
|
||||
// 验证调用
|
||||
verify(trafficLightService).findDeviceByAddress("10.0.0.1", 9090);
|
||||
verify(trafficLightService).getOrCreateDeviceByAddress("10.0.0.1", 9090, "DEFAULT_INTERSECTION");
|
||||
@ -223,92 +222,93 @@ class DataProcessingServiceTrafficLightTest {
|
||||
verify(trafficLightService).updateDeviceOnlineStatusByAddress("10.0.0.1", 9090, true);
|
||||
verify(eventPublisher).publishEvent(any(TrafficLightStatusEvent.class));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testProcessTrafficLightSignal_InvalidFormat() {
|
||||
// 测试无效格式消息
|
||||
String invalidMessage = "invalid message format";
|
||||
|
||||
|
||||
// Mock解析器行为
|
||||
when(trafficLightSignalParser.isValidMessageFormat(invalidMessage)).thenReturn(false);
|
||||
when(trafficLightSignalParser.isValidSignal(invalidMessage)).thenReturn(false);
|
||||
|
||||
|
||||
// 执行测试
|
||||
dataProcessingService.processTrafficLightSignal(invalidMessage);
|
||||
|
||||
|
||||
// 验证只调用了格式检查,没有进行后续处理
|
||||
verify(trafficLightSignalParser).isValidMessageFormat(invalidMessage);
|
||||
verify(trafficLightSignalParser).isValidSignal(invalidMessage);
|
||||
verifyNoInteractions(trafficLightService);
|
||||
verifyNoInteractions(intersectionService);
|
||||
verifyNoInteractions(eventPublisher);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testProcessTrafficLightSignal_InvalidStatus() {
|
||||
// 测试解析出无效状态的情况
|
||||
String rawMessage = "('192.168.1.100', 8082) - {\"DI-11\":0}";
|
||||
|
||||
String jsonSignal = "{\"DI-11\":0}";
|
||||
String ipAddress = "192.168.1.100";
|
||||
Integer port = 8082;
|
||||
|
||||
TrafficLightStatus invalidStatus = TrafficLightStatus.builder()
|
||||
.timestamp(0) // 无效时间戳
|
||||
.rawSignal(rawMessage)
|
||||
.rawSignal(jsonSignal)
|
||||
.build();
|
||||
|
||||
|
||||
// Mock解析器行为
|
||||
when(trafficLightSignalParser.isValidMessageFormat(rawMessage)).thenReturn(true);
|
||||
when(trafficLightSignalParser.parseSignalWithAddress(rawMessage)).thenReturn(invalidStatus);
|
||||
|
||||
when(trafficLightSignalParser.parseSignalWithAddress(jsonSignal, ipAddress, port)).thenReturn(invalidStatus);
|
||||
|
||||
// 执行测试
|
||||
dataProcessingService.processTrafficLightSignal(rawMessage);
|
||||
|
||||
dataProcessingService.processTrafficLightSignalWithAddress(jsonSignal, ipAddress, port);
|
||||
|
||||
// 验证只进行了解析,没有后续处理
|
||||
verify(trafficLightSignalParser).parseSignalWithAddress(rawMessage);
|
||||
verify(trafficLightSignalParser).parseSignalWithAddress(jsonSignal, ipAddress, port);
|
||||
verifyNoInteractions(trafficLightService);
|
||||
verifyNoInteractions(intersectionService);
|
||||
verifyNoInteractions(eventPublisher);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testProcessTrafficLightSignal_EmptyMessage() {
|
||||
// 测试空消息
|
||||
dataProcessingService.processTrafficLightSignal(null);
|
||||
dataProcessingService.processTrafficLightSignal("");
|
||||
dataProcessingService.processTrafficLightSignal(" ");
|
||||
|
||||
|
||||
// 验证没有任何处理
|
||||
verifyNoInteractions(trafficLightSignalParser);
|
||||
verifyNoInteractions(trafficLightService);
|
||||
verifyNoInteractions(intersectionService);
|
||||
verifyNoInteractions(eventPublisher);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testProcessTrafficLightSignal_DeviceNotFound() {
|
||||
// 测试设备不存在且无法创建的情况
|
||||
String rawMessage = "('172.16.0.1', 8083) - {\"DI-11\":1}";
|
||||
|
||||
String jsonSignal = "{\"DI-11\":1}";
|
||||
String ipAddress = "172.16.0.1";
|
||||
Integer port = 8083;
|
||||
|
||||
TrafficLightStatus statusWithoutDevice = TrafficLightStatus.builder()
|
||||
.ipAddress("172.16.0.1")
|
||||
.port(8083)
|
||||
.nsStatus(SignalState.RED)
|
||||
.ewStatus(SignalState.RED)
|
||||
.timestamp(System.currentTimeMillis() * 1000)
|
||||
.rawSignal(rawMessage)
|
||||
.rawSignal(jsonSignal)
|
||||
.build();
|
||||
|
||||
|
||||
// Mock解析器行为
|
||||
when(trafficLightSignalParser.isValidMessageFormat(rawMessage)).thenReturn(true);
|
||||
when(trafficLightSignalParser.parseSignalWithAddress(rawMessage)).thenReturn(statusWithoutDevice);
|
||||
|
||||
when(trafficLightSignalParser.parseSignalWithAddress(jsonSignal, ipAddress, port))
|
||||
.thenReturn(statusWithoutDevice);
|
||||
|
||||
// Mock设备查找失败
|
||||
when(trafficLightService.findDeviceByAddress("172.16.0.1", 8083))
|
||||
.thenReturn(Optional.empty());
|
||||
when(trafficLightService.getOrCreateDeviceByAddress("172.16.0.1", 8083, "DEFAULT_INTERSECTION"))
|
||||
.thenThrow(new RuntimeException("创建设备失败"));
|
||||
|
||||
|
||||
// 执行测试
|
||||
dataProcessingService.processTrafficLightSignal(rawMessage);
|
||||
|
||||
dataProcessingService.processTrafficLightSignalWithAddress(jsonSignal, ipAddress, port);
|
||||
|
||||
// 验证尝试了设备查找和创建,但没有后续处理
|
||||
verify(trafficLightService).findDeviceByAddress("172.16.0.1", 8083);
|
||||
verify(trafficLightService).getOrCreateDeviceByAddress("172.16.0.1", 8083, "DEFAULT_INTERSECTION");
|
||||
|
||||
Loading…
Reference in New Issue
Block a user