| | |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.PutMapping; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | import org.springframework.web.server.ResponseStatusException; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | |
| | | import com.battery.device.simulator.BtsDevelopmentSimulator.StateSnapshot; |
| | | import com.battery.device.api.discovery.DeviceDiscoveryCandidateStore; |
| | | import com.battery.device.api.model.DeviceWorkStatus; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorHistoryFaults; |
| | | import com.battery.device.simulator.BtsSimulatorStateStore.CollectorMetricState; |
| | | import com.battery.device.simulator.DevelopmentCollectorSimulation.CollectorHistoryPage; |
| | | import com.battery.device.simulator.DevelopmentCollectorSimulation.CollectorRealtimeSnapshot; |
| | | import com.battery.device.simulator.BtsDevelopmentSimulator.PlaybackSnapshot; |
| | | |
| | | /** 本机临时 BTS 模拟器控制 API。 */ |
| | | @Anonymous |
| | |
| | | return simulator.snapshot(); |
| | | } |
| | | |
| | | /** 人工清空长期状态并恢复一台默认检测柜和采集器。 */ |
| | | /** 人工清空模拟配置并恢复默认检测柜和采集器。 */ |
| | | @PostMapping("/dev/bts-simulator/reset") |
| | | public StateSnapshot reset() |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** 配置采集器采样频率和可重复的历史下载故障场景。 */ |
| | | @PutMapping("/dev/bts-simulator/collectors/{collectorId}/sampling") |
| | | public StateSnapshot configureCollectorSampling(@PathVariable int collectorId, |
| | | @RequestBody CollectorSamplingCommand command) |
| | | { |
| | | try |
| | | { |
| | | simulator.configureCollectorSampling(collectorId, command.sampleIntervalMs(), |
| | | new CollectorHistoryFaults(command.missingSequences(), command.duplicateSequence(), |
| | | command.conflictingSequence(), command.outOfOrder())); |
| | | return simulator.snapshot(); |
| | | } |
| | | catch (IllegalArgumentException exception) |
| | | { |
| | | throw badRequest(exception); |
| | | } |
| | | } |
| | | |
| | | /** 配置稳定 S 通道的固定和动态测量项。 */ |
| | | @PutMapping("/dev/bts-simulator/collectors/{collectorId}/channels/{channelCode}") |
| | | public StateSnapshot configureCollectorChannel(@PathVariable int collectorId, |
| | |
| | | } |
| | | } |
| | | |
| | | /** 查询采集器最新实时快照;离线时保留最后观测并明确返回离线事实。 */ |
| | | /** 请求采集器当前实时快照;不可访问或离线时返回空测量。 */ |
| | | @GetMapping("/dev/bts-simulator/collectors/{collectorId}/realtime") |
| | | public CollectorRealtimeSnapshot collectorRealtime(@PathVariable int collectorId) |
| | | { |
| | | try |
| | | { |
| | | return simulator.collectorRealtime(collectorId); |
| | | } |
| | | catch (IllegalArgumentException exception) |
| | | { |
| | | throw badRequest(exception); |
| | | } |
| | | } |
| | | |
| | | /** 按偏移量分页下载采集器模拟历史,每页最多 1000 条。 */ |
| | | @GetMapping("/dev/bts-simulator/collectors/{collectorId}/history") |
| | | public CollectorHistoryPage collectorHistory(@PathVariable int collectorId, |
| | | @RequestParam(defaultValue = "0") long offset, @RequestParam(defaultValue = "100") int limit) |
| | | { |
| | | try |
| | | { |
| | | return simulator.collectorHistory(collectorId, offset, limit); |
| | | } |
| | | catch (IllegalArgumentException exception) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | /** 返回检测柜通道播放、record、step 和 cycle 的当前快照。 */ |
| | | @GetMapping("/dev/bts-simulator/devices/{deviceId}/channels/{channelId}/playback") |
| | | public PlaybackSnapshot btsPlayback(@PathVariable int deviceId, @PathVariable int channelId) |
| | | /** 修改软件可访问性,设备配置继续保留。 */ |
| | | @PutMapping("/dev/bts-simulator/software") |
| | | public StateSnapshot software(@RequestBody SoftwareCommand command) |
| | | { |
| | | try { return simulator.btsPlayback(deviceId, channelId); } |
| | | catch (IllegalArgumentException exception) { throw badRequest(exception); } |
| | | if (command == null || command.accessible() == null) |
| | | throw badRequest(new IllegalArgumentException("accessible must be true or false")); |
| | | simulator.setSoftwareAccessible(command.accessible()); |
| | | synchronizeOnlineStatusIfConfigured(); |
| | | return simulator.snapshot(); |
| | | } |
| | | |
| | | @GetMapping("/dev/bts-simulator/devices/{deviceId}/channels/{channelId}/records") |
| | | public List<com.battery.device.simulator.BtsSimulatorStateStore.BtsHistoryRecord> btsRecords( |
| | | @PathVariable int deviceId, @PathVariable int channelId) |
| | | { |
| | | try { return simulator.btsRecords(deviceId, channelId); } |
| | | catch (IllegalArgumentException exception) { throw badRequest(exception); } |
| | | } |
| | | |
| | | @GetMapping("/dev/bts-simulator/devices/{deviceId}/channels/{channelId}/steps") |
| | | public List<BtsDevelopmentSimulator.BtsStepRecord> btsSteps( |
| | | @PathVariable int deviceId, @PathVariable int channelId) |
| | | { |
| | | try { return simulator.btsSteps(deviceId, channelId); } |
| | | catch (IllegalArgumentException exception) { throw badRequest(exception); } |
| | | } |
| | | |
| | | @GetMapping("/dev/bts-simulator/devices/{deviceId}/channels/{channelId}/cycles") |
| | | public List<BtsDevelopmentSimulator.BtsCycleRecord> btsCycles( |
| | | @PathVariable int deviceId, @PathVariable int channelId) |
| | | { |
| | | try { return simulator.btsCycles(deviceId, channelId); } |
| | | catch (IllegalArgumentException exception) { throw badRequest(exception); } |
| | | } |
| | | |
| | | /** 设置检测柜通道演示倍速。 */ |
| | | @PutMapping("/dev/bts-simulator/devices/{deviceId}/channels/{channelId}/playback") |
| | | public PlaybackSnapshot configureBtsPlayback(@PathVariable int deviceId, @PathVariable int channelId, |
| | | @RequestBody PlaybackCommand command) |
| | | /** 修改采集器通道当前工作状态。 */ |
| | | @PutMapping("/dev/bts-simulator/collectors/{collectorId}/channels/{channelCode}/status") |
| | | public StateSnapshot collectorChannelStatus(@PathVariable int collectorId, @PathVariable String channelCode, |
| | | @RequestBody CollectorChannelStatusCommand command) |
| | | { |
| | | try |
| | | { |
| | | if (command.speedMultiplier() != null) simulator.setBtsSpeed(deviceId, channelId, command.speedMultiplier()); |
| | | if (command.playing() != null) |
| | | { |
| | | if (command.playing()) simulator.playBts(deviceId, channelId); |
| | | else simulator.pauseBts(deviceId, channelId); |
| | | } |
| | | return simulator.btsPlayback(deviceId, channelId); |
| | | simulator.updateCollectorChannelStatus(collectorId, channelCode, command.workStatus()); |
| | | return simulator.snapshot(); |
| | | } |
| | | catch (IllegalArgumentException exception) { throw badRequest(exception); } |
| | | } |
| | | |
| | | @PostMapping("/dev/bts-simulator/devices/{deviceId}/channels/{channelId}/playback/play") |
| | | public PlaybackSnapshot playBts(@PathVariable int deviceId, @PathVariable int channelId) |
| | | { |
| | | try { simulator.playBts(deviceId, channelId); return simulator.btsPlayback(deviceId, channelId); } |
| | | catch (IllegalArgumentException exception) { throw badRequest(exception); } |
| | | } |
| | | |
| | | @PostMapping("/dev/bts-simulator/devices/{deviceId}/channels/{channelId}/playback/pause") |
| | | public PlaybackSnapshot pauseBts(@PathVariable int deviceId, @PathVariable int channelId) |
| | | { |
| | | try { simulator.pauseBts(deviceId, channelId); return simulator.btsPlayback(deviceId, channelId); } |
| | | catch (IllegalArgumentException exception) { throw badRequest(exception); } |
| | | } |
| | | |
| | | @PostMapping("/dev/bts-simulator/devices/{deviceId}/channels/{channelId}/playback/resume") |
| | | public PlaybackSnapshot resumeBts(@PathVariable int deviceId, @PathVariable int channelId) |
| | | { |
| | | try { simulator.resumeBts(deviceId, channelId); return simulator.btsPlayback(deviceId, channelId); } |
| | | catch (IllegalArgumentException exception) { throw badRequest(exception); } |
| | | } |
| | | |
| | | @PostMapping("/dev/bts-simulator/devices/{deviceId}/channels/{channelId}/playback/next-step") |
| | | public PlaybackSnapshot nextBtsStep(@PathVariable int deviceId, @PathVariable int channelId) |
| | | { |
| | | try { simulator.nextBtsStep(deviceId, channelId); return simulator.btsPlayback(deviceId, channelId); } |
| | | catch (IllegalArgumentException exception) { throw badRequest(exception); } |
| | | } |
| | | |
| | | @PostMapping("/dev/bts-simulator/devices/{deviceId}/channels/{channelId}/playback/next-cycle") |
| | | public PlaybackSnapshot nextBtsCycle(@PathVariable int deviceId, @PathVariable int channelId) |
| | | { |
| | | try { simulator.nextBtsCycle(deviceId, channelId); return simulator.btsPlayback(deviceId, channelId); } |
| | | catch (IllegalArgumentException exception) { throw badRequest(exception); } |
| | | } |
| | | |
| | | @PostMapping("/dev/bts-simulator/devices/{deviceId}/channels/{channelId}/playback/reset") |
| | | public PlaybackSnapshot resetBts(@PathVariable int deviceId, @PathVariable int channelId) |
| | | { |
| | | try { simulator.resetBts(deviceId, channelId); return simulator.btsPlayback(deviceId, channelId); } |
| | | catch (IllegalArgumentException exception) { throw badRequest(exception); } |
| | | } |
| | | |
| | |
| | | |
| | | public record CollectorStateCommand(String ip, int channelCount, boolean online) { } |
| | | |
| | | public record CollectorSamplingCommand(int sampleIntervalMs, List<Long> missingSequences, |
| | | Long duplicateSequence, Long conflictingSequence, boolean outOfOrder) |
| | | { |
| | | public CollectorSamplingCommand |
| | | { |
| | | missingSequences = missingSequences == null ? List.of() : List.copyOf(missingSequences); |
| | | } |
| | | } |
| | | |
| | | public record CollectorChannelCommand(List<CollectorMetricCommand> metrics) { } |
| | | |
| | | public record CollectorMetricCommand(String metricCode, BigDecimal value, String unit) { } |
| | | |
| | | public record PlaybackCommand(Integer speedMultiplier, Boolean playing) { } |
| | | public record SoftwareCommand(Boolean accessible) { } |
| | | |
| | | public record CollectorChannelStatusCommand(DeviceWorkStatus workStatus) { } |
| | | } |