| | |
| | | import java.time.ZoneId; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.ArrayList; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import javax.xml.stream.XMLInputFactory; |
| | | import javax.xml.stream.XMLStreamConstants; |
| | | import javax.xml.stream.XMLStreamReader; |
| | | import com.battery.device.api.DeviceAdapter; |
| | | import com.battery.device.api.model.DeviceWorkStatus; |
| | | import com.battery.device.api.model.DeviceConnectionStatus; |
| | | import com.battery.device.api.model.DeviceIdentity; |
| | |
| | | import com.battery.device.api.model.DetectedDeviceMetadata; |
| | | import com.battery.device.api.model.ChannelIdentity; |
| | | import com.battery.device.api.model.AdapterCapabilities; |
| | | import com.battery.device.api.model.RealtimeSnapshot; |
| | | import com.battery.device.api.DeviceObservationAdapter; |
| | | import com.battery.device.api.TestDataObservationAdapter; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore; |
| | |
| | | import com.battery.device.simulator.DevelopmentCollectorSimulation; |
| | | import com.battery.device.simulator.DevelopmentCollectorSimulation.CollectorRealtimeSnapshot; |
| | | |
| | | /** 提供由开发后端托管的临时只读 BTS 模拟端点。 */ |
| | | public final class BtsDevelopmentSimulator implements TestDataObservationAdapter |
| | | /** |
| | | * 提供由开发后端托管的临时只读 BTS 模拟端点。 |
| | | * 同时实现发现与测试数据观测契约:模拟器直接暴露自身状态,因此发现与取数按同一实例解析, |
| | | * 不再需要单独注入一个扩展观测 Bean。TCP 端点仍保留给协议层测试使用。 |
| | | */ |
| | | public final class BtsDevelopmentSimulator implements DeviceAdapter, TestDataObservationAdapter |
| | | { |
| | | public static final String HOST = "127.0.0.1"; |
| | | public static final int DEFAULT_PORT = 15020; |
| | |
| | | for (ChannelIdentity requested : channels) result.put(requested, observation(requested)); |
| | | recordRequest("observe", channels.toString(), result.toString()); |
| | | return java.util.Map.copyOf(result); |
| | | } |
| | | |
| | | /** 直接提供模拟器实时快照;不可观测通道不出现在结果里,与 BTS 协议解析后的语义一致。 */ |
| | | @Override |
| | | public synchronized Map<ChannelIdentity, RealtimeSnapshot> inquire(Set<ChannelIdentity> channels) |
| | | { |
| | | if (channels == null || channels.isEmpty()) return Map.of(); |
| | | Map<ChannelIdentity, RealtimeSnapshot> result = new LinkedHashMap<>(); |
| | | for (ChannelIdentity requested : channels) |
| | | { |
| | | if (!canObserve(requested)) continue; |
| | | CabinetRealtime measurement = cabinetMeasurement(requested); |
| | | if (measurement == null) continue; |
| | | DeviceObservation observed = observation(requested); |
| | | result.put(requested, new RealtimeSnapshot(requested, observed.workStatus(), measurement.cycleNo(), |
| | | measurement.stepNo(), measurement.stepType(), null, BigDecimal.valueOf(measurement.currentA()), |
| | | BigDecimal.valueOf(measurement.voltageV()), BigDecimal.valueOf(measurement.capacityAh()), |
| | | BigDecimal.valueOf(measurement.energyWh()), totalTimeSeconds(requested), |
| | | measurement.relativeTimeSeconds(), null, measurement.serverReceivedAt(), Map.of(), |
| | | DeviceConnectionStatus.ONLINE, measurement.deviceTime(), List.of(), null)); |
| | | } |
| | | recordRequest("inquire", channels.toString(), result.toString()); |
| | | return Map.copyOf(result); |
| | | } |
| | | |
| | | private long totalTimeSeconds(ChannelIdentity identity) |
| | | { |
| | | return requireDevice(identity.devid()).channels().get(identity.chlid() - 1).configuration().totalTimeSeconds(); |
| | | } |
| | | |
| | | private DeviceObservation observation(ChannelIdentity requested) |
| | |
| | | |
| | | /** 请求采集器当前配置值;软件不可访问或设备离线时返回空测量。 */ |
| | | @Override |
| | | public synchronized CollectorRealtime latestCollector(String collectorCode) |
| | | public synchronized CollectorRealtime latestCollector(String adapterCode, String collectorCode) |
| | | { |
| | | CollectorState collector = state.collectors().stream().filter(item -> item.deviceCode().equals(collectorCode)) |
| | | .findFirst().orElse(null); |