yeg
2026-08-27 ebd47e950c8d45f5cc21336f4996857de58e0ea6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
package com.ruoyi.web.controller.device;
 
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
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.RestController;
import org.springframework.web.server.ResponseStatusException;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.device.bts.BtsDevelopmentSimulator;
import com.ruoyi.device.bts.BtsDevelopmentSimulator.StateSnapshot;
import com.ruoyi.device.discovery.DeviceDiscoveryCandidateStore;
import com.ruoyi.device.model.DeviceWorkStatus;
 
/** 本机临时 BTS 模拟器控制 API。 */
@Anonymous
@RestController
public class BtsDevelopmentSimulatorController
{
    private final BtsDevelopmentSimulator simulator;
    private final DeviceDiscoveryCandidateStore candidateStore;
 
    public BtsDevelopmentSimulatorController(BtsDevelopmentSimulator simulator,
            DeviceDiscoveryCandidateStore candidateStore)
    {
        this.simulator = simulator;
        this.candidateStore = candidateStore;
    }
 
    /** 返回临时控制页;匿名放行后仍由本机拦截器限制来源。 */
    @GetMapping(value = "/dev/bts-simulator.html", produces = MediaType.TEXT_HTML_VALUE)
    public Resource page()
    {
        return new ClassPathResource("static/dev/bts-simulator.html");
    }
 
    /** 返回模拟器、虚拟设备、通道和最近请求的当前快照。 */
    @GetMapping("/dev/bts-simulator/state")
    public StateSnapshot state()
    {
        return simulator.snapshot();
    }
 
    /** 人工清空长期状态并恢复一台默认检测柜和采集器。 */
    @PostMapping("/dev/bts-simulator/reset")
    public StateSnapshot reset()
    {
        simulator.reset();
        candidateStore.removeAdapter(BtsDevelopmentSimulator.ADAPTER_CODE);
        return simulator.snapshot();
    }
 
    /** 添加一台虚拟设备。 */
    @PostMapping("/dev/bts-simulator/devices")
    public StateSnapshot createDevice(@RequestBody CreateDeviceCommand command)
    {
        try
        {
            simulator.addDevice(command.ip(), command.channelCount());
            return simulator.snapshot();
        }
        catch (IllegalArgumentException exception)
        {
            throw badRequest(exception);
        }
    }
 
    /** 修改指定虚拟设备的地址、通道数和在线状态。 */
    @PutMapping("/dev/bts-simulator/devices/{deviceId}")
    public StateSnapshot updateDevice(@PathVariable int deviceId, @RequestBody DeviceStateCommand command)
    {
        try
        {
            simulator.updateDevice(deviceId, command.ip(), command.channelCount(), command.online());
            return simulator.snapshot();
        }
        catch (IllegalArgumentException exception)
        {
            throw badRequest(exception);
        }
    }
 
    /** 删除指定虚拟设备。 */
    @DeleteMapping("/dev/bts-simulator/devices/{deviceId}")
    public StateSnapshot deleteDevice(@PathVariable int deviceId)
    {
        try
        {
            simulator.deleteDevice(deviceId);
            return simulator.snapshot();
        }
        catch (IllegalArgumentException exception)
        {
            throw badRequest(exception);
        }
    }
 
    /** 添加一台与检测柜分开配置的虚拟采集器。 */
    @PostMapping("/dev/bts-simulator/collectors")
    public StateSnapshot createCollector(@RequestBody CreateCollectorCommand command)
    {
        try
        {
            simulator.addCollector(command.ip(), command.channelCount());
            return simulator.snapshot();
        }
        catch (IllegalArgumentException exception)
        {
            throw badRequest(exception);
        }
    }
 
    /** 修改虚拟采集器的地址、通道数和在线状态。 */
    @PutMapping("/dev/bts-simulator/collectors/{collectorId}")
    public StateSnapshot updateCollector(@PathVariable int collectorId,
            @RequestBody CollectorStateCommand command)
    {
        try
        {
            simulator.updateCollector(collectorId, command.ip(), command.channelCount(), command.online());
            return simulator.snapshot();
        }
        catch (IllegalArgumentException exception)
        {
            throw badRequest(exception);
        }
    }
 
    /** 删除指定虚拟采集器。 */
    @DeleteMapping("/dev/bts-simulator/collectors/{collectorId}")
    public StateSnapshot deleteCollector(@PathVariable int collectorId)
    {
        try
        {
            simulator.deleteCollector(collectorId);
            return simulator.snapshot();
        }
        catch (IllegalArgumentException exception)
        {
            throw badRequest(exception);
        }
    }
 
    /** 修改指定虚拟设备通道的在线和工作状态。 */
    @PutMapping("/dev/bts-simulator/devices/{deviceId}/channels/{channelId}")
    public StateSnapshot updateChannel(@PathVariable int deviceId, @PathVariable int channelId,
            @RequestBody ChannelStateCommand command)
    {
        try
        {
            simulator.updateChannel(deviceId, channelId, command.online(), command.workStatus());
            return simulator.snapshot();
        }
        catch (IllegalArgumentException exception)
        {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, exception.getMessage(), exception);
        }
    }
 
    private ResponseStatusException badRequest(IllegalArgumentException exception)
    {
        return new ResponseStatusException(HttpStatus.BAD_REQUEST, exception.getMessage(), exception);
    }
 
    public record CreateDeviceCommand(String ip, int channelCount) { }
 
    public record DeviceStateCommand(String ip, int channelCount, boolean online) { }
 
    public record ChannelStateCommand(boolean online, DeviceWorkStatus workStatus) { }
 
    public record CreateCollectorCommand(String ip, int channelCount) { }
 
    public record CollectorStateCommand(String ip, int channelCount, boolean online) { }
}