From bd50f1b756c1da2dbf92f6541407ad40f455e24a Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期六, 05 九月 2026 00:17:52 +0800
Subject: [PATCH] 建立厂商无关设备观测接缝
---
battery-device-simulator/src/main/java/com/battery/device/simulator/BtsDevelopmentSimulator.java | 91 +++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 87 insertions(+), 4 deletions(-)
diff --git a/battery-device-simulator/src/main/java/com/battery/device/simulator/BtsDevelopmentSimulator.java b/battery-device-simulator/src/main/java/com/battery/device/simulator/BtsDevelopmentSimulator.java
index 8151eb4..0067285 100644
--- a/battery-device-simulator/src/main/java/com/battery/device/simulator/BtsDevelopmentSimulator.java
+++ b/battery-device-simulator/src/main/java/com/battery/device/simulator/BtsDevelopmentSimulator.java
@@ -12,6 +12,14 @@
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamReader;
import com.battery.device.model.DeviceWorkStatus;
+import com.battery.device.model.DeviceConnectionStatus;
+import com.battery.device.model.DeviceIdentity;
+import com.battery.device.model.DeviceObservation;
+import com.battery.device.model.DetectedChannel;
+import com.battery.device.model.DetectedDeviceMetadata;
+import com.battery.device.model.ChannelIdentity;
+import com.battery.device.model.AdapterCapabilities;
+import com.battery.device.api.DeviceObservationAdapter;
import com.battery.device.simulator.BtsSimulatorStateStore;
import com.battery.device.simulator.BtsSimulatorStateStore.ChannelState;
import com.battery.device.simulator.BtsSimulatorStateStore.ChannelTombstone;
@@ -35,7 +43,7 @@
import com.battery.device.simulator.DevelopmentCollectorSimulation.CollectorRealtimeSnapshot;
/** 提供由开发后端托管的临时只读 BTS 模拟端点。 */
-public final class BtsDevelopmentSimulator implements AutoCloseable
+public final class BtsDevelopmentSimulator implements DeviceObservationAdapter
{
public static final String HOST = "127.0.0.1";
public static final int DEFAULT_PORT = 15020;
@@ -58,6 +66,71 @@
private static final long SIMULATED_RECORD_INTERVAL_SECONDS = 60L;
private static final DateTimeFormatter BTS_HISTORY_TIME = DateTimeFormatter.ofPattern("yyyy-MM-dd HH.mm.ss")
.withZone(ZoneId.of("Asia/Hong_Kong"));
+
+ @Override
+ public String adapterCode()
+ {
+ return ADAPTER_CODE;
+ }
+
+ @Override
+ public AdapterCapabilities capabilities()
+ {
+ return AdapterCapabilities.observeOnly();
+ }
+
+ /** 直接提供模拟器当前拓扑,供不需要 TCP/XML 的契约测试使用。 */
+ @Override
+ public synchronized List<DetectedChannel> discoverChannels()
+ {
+ List<DetectedChannel> result = new ArrayList<>();
+ for (DeviceState device : state.devices())
+ {
+ BtsDeviceProfile profile = profileFor(device);
+ for (ChannelState channel : device.channels())
+ {
+ ChannelIdentity identity = new ChannelIdentity(ADAPTER_CODE, profile.devtype(), device.deviceId(),
+ profile.subDeviceId(), channel.channelId());
+ result.add(new DetectedChannel(identity, device.ip(), device.online() && channel.online(),
+ new DetectedDeviceMetadata(profile.name(), profile.manufacturer(), profile.model(),
+ simulatorMac(profile.devtype(), device.deviceId()))));
+ }
+ }
+ return List.copyOf(result);
+ }
+
+ /** 直接提供模拟器观测;离线通道不保留上一次测量或工步事实。 */
+ @Override
+ public synchronized java.util.Map<ChannelIdentity, DeviceObservation> observe(
+ java.util.Set<ChannelIdentity> channels)
+ {
+ if (channels == null || channels.isEmpty()) return java.util.Map.of();
+ java.util.Map<ChannelIdentity, DeviceObservation> result = new java.util.LinkedHashMap<>();
+ for (ChannelIdentity requested : channels)
+ {
+ DeviceState device = state.devices().stream().filter(item -> item.deviceId() == requested.devid())
+ .findFirst().orElse(null);
+ ChannelState channel = device == null ? null : device.channels().stream()
+ .filter(item -> item.channelId() == requested.chlid()).findFirst().orElse(null);
+ if (device == null || channel == null || !ADAPTER_CODE.equals(requested.adapterCode())
+ || !device.online() || !channel.online())
+ {
+ result.put(requested, DeviceObservation.offline(requested, "OFFLINE"));
+ continue;
+ }
+ BtsDeviceProfile profile = profileFor(device);
+ if (requested.devtype() != profile.devtype() || requested.subdevid() != profile.subDeviceId())
+ {
+ result.put(requested, DeviceObservation.offline(requested, "OFFLINE"));
+ continue;
+ }
+ result.put(requested, new DeviceObservation(
+ new DeviceIdentity(ADAPTER_CODE, profile.devtype(), device.deviceId(), profile.subDeviceId()),
+ requested, DeviceConnectionStatus.ONLINE, channel.workStatus(), List.of(), null,
+ java.util.Map.of(), null));
+ }
+ return java.util.Map.copyOf(result);
+ }
/** 启动仅监听 IPv4 本机回环地址的开发模拟器;传入 0 时由系统分配测试端口。 */
public BtsDevelopmentSimulator(int port) throws IOException
@@ -721,7 +794,10 @@
.append(decimal(voltage)).append("\" capacity=\"").append(decimal(capacity))
.append("\" energy=\"").append(decimal(energy)).append("\" totaltime=\"")
.append(working ? tick : 0).append("\" relativetime=\"").append(working ? tick : 0)
- .append("\" open_or_close=\"0\" log_code=\"0\"/>");
+ .append("\" open_or_close=\"0\" log_code=\"0\">")
+ // 模拟器返回当前设备方案,供统一观测模型展示;不代表真实 BTS 的完整方案字段。
+ .append("<plan><step step_no=\"").append(stepNo).append("\" step_type=\"")
+ .append(stepType).append("\" name=\"").append(stepType).append("\"/></plan></inquire>");
}
return response.append("</list></bts>").toString();
}
@@ -1203,10 +1279,17 @@
}
@Override
- public synchronized void close() throws Exception
+ public synchronized void close()
{
running = false;
- simulator.close();
+ try
+ {
+ simulator.close();
+ }
+ catch (Exception exception)
+ {
+ throw new IllegalStateException("关闭开发模拟器失败", exception);
+ }
}
private record ObservedChannel(int deviceId, ChannelState channel) { }
--
Gitblit v1.7.1