gongchunyi
21 小时以前 e9b4ceeea014f9d81263672f3d9c46a567c39591
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
package com.ruoyi.energymeter.controller;
 
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.energymeter.dto.EnergyMeterDeviceQuery;
import com.ruoyi.energymeter.dto.MeterBindRequest;
import com.ruoyi.energymeter.dto.MeterCollectRequest;
import com.ruoyi.energymeter.dto.MeterManualBindRequest;
import com.ruoyi.energymeter.dto.MeterReadingRequest;
import com.ruoyi.energymeter.dto.MeterUpdateRequest;
import com.ruoyi.energymeter.dto.MeterVerifyRequest;
import com.ruoyi.energymeter.pojo.EnergyMeterDevice;
import com.ruoyi.energymeter.pojo.EnergyMeterMeasurement;
import com.ruoyi.energymeter.service.EnergyMeterDeviceService;
import com.ruoyi.energymeter.service.EnergyMeterDemoService;
import com.ruoyi.energymeter.service.EnergyMeterStatService;
import com.ruoyi.energymeter.service.EnergyMeterSyncService;
import com.ruoyi.energymeter.service.ElectricMeterDashboardService;
import com.ruoyi.energymeter.util.EnergyMeterSupport;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
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.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.RestController;
 
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
 
/**
 * 水电表接入与查表接口。
 *
 * <p>前端只调用本系统后端,第三方授权码不会下发到浏览器。</p>
 */
@RestController
@Tag(name = "水电表监测")
@RequestMapping("/energyMeter")
@RequiredArgsConstructor
public class EnergyMeterController extends BaseController {
 
    private final EnergyMeterDeviceService deviceService;
    private final EnergyMeterSyncService syncService;
    private final EnergyMeterStatService statService;
    private final EnergyMeterDemoService demoService;
    private final ElectricMeterDashboardService electricDashboardService;
 
    @GetMapping("/devices")
    @Operation(summary = "设备列表-分页查询")
    @Log(title = "水电表监测-设备列表", businessType = BusinessType.OTHER)
    public AjaxResult devices(Page<EnergyMeterDevice> page, EnergyMeterDeviceQuery query) {
        IPage<EnergyMeterDevice> result = deviceService.pageDevices(page, query);
        return AjaxResult.success(result);
    }
 
    @GetMapping("/devices/options")
    @Operation(summary = "设备下拉选项")
    public AjaxResult deviceOptions(@RequestParam(required = false) String meterType) {
        return AjaxResult.success(deviceService.listDeviceOptions(meterType));
    }
 
    @PostMapping("/devices/verify")
    @Operation(summary = "验证并读取第三方档案")
    @Log(title = "水电表监测-档案验证", businessType = BusinessType.OTHER)
    public AjaxResult verify(@RequestBody MeterVerifyRequest request) {
        return AjaxResult.success(deviceService.verifyArchive(request.getMeterType(), request.getMeterAddress()));
    }
 
    @PostMapping("/devices")
    @Operation(summary = "新增本地绑定")
    @Log(title = "水电表监测-新增绑定", businessType = BusinessType.INSERT)
    public AjaxResult add(@RequestBody MeterBindRequest request) {
        return AjaxResult.success(deviceService.bind(request));
    }
 
    @PutMapping("/devices/{id}")
    @Operation(summary = "修改设备本地字段/启停用")
    @Log(title = "表具台账-修改设备", businessType = BusinessType.UPDATE)
    public AjaxResult update(@PathVariable Long id, @RequestBody MeterUpdateRequest request) {
        return AjaxResult.success(deviceService.updateLocal(id, request));
    }
 
    @PostMapping("/devices/manual")
    @Operation(summary = "新增手工抄表设备(水表/电表/气表)")
    @Log(title = "表具台账-新增手工抄表设备", businessType = BusinessType.INSERT)
    public AjaxResult addManual(@RequestBody MeterManualBindRequest request) {
        return AjaxResult.success(deviceService.addManual(request));
    }
 
    @DeleteMapping("/devices/{id}")
    @Operation(summary = "删除设备(初始化设备与第三方接入设备不允许删除)")
    @Log(title = "表具台账-删除设备", businessType = BusinessType.DELETE)
    public AjaxResult remove(@PathVariable Long id) {
        deviceService.removeDevice(id);
        return AjaxResult.success();
    }
 
    @GetMapping("/devices/{id}/readings")
    @Operation(summary = "手工抄表记录分页")
    public AjaxResult readings(@PathVariable Long id,
                               @RequestParam(defaultValue = "1") long current,
                               @RequestParam(defaultValue = "20") long size) {
        return AjaxResult.success(deviceService.pageReadings(id, current, size));
    }
 
    @PostMapping("/devices/{id}/readings")
    @Operation(summary = "录入手工抄表表码")
    @Log(title = "表具台账-手工录表", businessType = BusinessType.INSERT)
    public AjaxResult addReading(@PathVariable Long id, @RequestBody MeterReadingRequest request) {
        return AjaxResult.success(deviceService.addReading(id, request));
    }
 
    @DeleteMapping("/devices/{id}/readings/{readingId}")
    @Operation(summary = "删除手工抄表记录")
    @Log(title = "表具台账-删除抄表记录", businessType = BusinessType.DELETE)
    public AjaxResult removeReading(@PathVariable Long id, @PathVariable Long readingId) {
        deviceService.removeReading(id, readingId);
        return AjaxResult.success();
    }
 
    @PostMapping("/devices/{id}/collect")
    @Operation(summary = "单台设备手动查表")
    @Log(title = "水电表监测-手动查表", businessType = BusinessType.OTHER)
    public AjaxResult collect(@PathVariable Long id,
                              @RequestBody(required = false) MeterCollectRequest request) {
        LocalDate start = request == null ? null : request.getStartDate();
        LocalDate end = request == null ? null : request.getEndDate();
        Boolean includeReadings = request == null ? null : request.getIncludeReadings();
        Long runId = syncService.triggerManual(List.of(id), start, end, includeReadings);
        return AjaxResult.success(runResult(runId));
    }
 
    @PostMapping("/devices/collect")
    @Operation(summary = "批量手动查表")
    @Log(title = "水电表监测-批量查表", businessType = BusinessType.OTHER)
    public AjaxResult collectBatch(@RequestBody MeterCollectRequest request) {
        List<Long> meterIds = new ArrayList<>();
        if (request.getMeterIds() != null) {
            meterIds.addAll(request.getMeterIds());
        }
        if (request.getMeterId() != null && !meterIds.contains(request.getMeterId())) {
            meterIds.add(request.getMeterId());
        }
        Long runId = syncService.triggerManual(meterIds, request.getStartDate(), request.getEndDate(),
                request.getIncludeReadings());
        return AjaxResult.success(runResult(runId));
    }
 
    @GetMapping("/devices/{id}/measurements")
    @Operation(summary = "设备读数/用量明细")
    public AjaxResult measurements(@PathVariable Long id,
                                   @RequestParam(required = false) String metricCode,
                                   @RequestParam(required = false) String granularity,
                                   @RequestParam(required = false) String start,
                                   @RequestParam(required = false) String end,
                                   @RequestParam(defaultValue = "1") long current,
                                   @RequestParam(defaultValue = "20") long size) {
        IPage<EnergyMeterMeasurement> page = statService.pageMeasurements(id, metricCode, granularity,
                parseDate(start), parseDate(end), current, size);
        return AjaxResult.success(page);
    }
 
    @GetMapping("/overview")
    @Operation(summary = "用能概览")
    public AjaxResult overview(@RequestParam(defaultValue = "WATER") String meterType,
                               @RequestParam(required = false) Long meterId,
                               @RequestParam(required = false) String month,
                               @RequestParam(required = false) Integer year) {
        return AjaxResult.success(statService.overview(meterType, meterId, month, year));
    }
 
    @GetMapping("/electric/dashboard")
    @Operation(summary = "电表实时看板:今日15分钟曲线与电能质量")
    public AjaxResult electricDashboard(@RequestParam(required = false) Long meterId,
                                        @RequestParam(defaultValue = "0") Integer weekOffset) {
        return AjaxResult.success(electricDashboardService.dashboard(meterId, weekOffset));
    }
 
    @PostMapping("/sync/trigger")
    @Operation(summary = "手动触发一次每日同步(排障用)")
    @Log(title = "水电表监测-触发同步", businessType = BusinessType.OTHER)
    public AjaxResult triggerDailySync() {
        return AjaxResult.success(runResult(syncService.triggerScheduledSync()));
    }
 
    @PostMapping("/sync/recover")
    @Operation(summary = "手动触发一次重试/超时恢复(排障用)")
    @Log(title = "水电表监测-触发恢复", businessType = BusinessType.OTHER)
    public AjaxResult recoverSync() {
        Map<String, Object> data = new LinkedHashMap<>();
        data.put("handled", syncService.recoverDueTasks());
        return AjaxResult.success(data);
    }
 
    @GetMapping("/providerStatus")
    @Operation(summary = "第三方接入模式")
    public AjaxResult providerStatus() {
        Map<String, Object> data = new LinkedHashMap<>();
        data.put("mockMode", deviceService.mockMode());
        return AjaxResult.success(data);
    }
 
    @PostMapping("/sync/gasSimulate")
    @Operation(summary = "生成气表演示数据(按天,默认今天;同一天重复执行不会重复写入)")
    @Log(title = "表具台账-气表演示数据", businessType = BusinessType.OTHER)
    public AjaxResult gasSimulate(@RequestParam(required = false) String date) {
        LocalDate day = StringUtils.isBlank(date) ? EnergyMeterSupport.today() : parseDate(date);
        Map<String, Object> data = new LinkedHashMap<>();
        data.put("date", day.toString());
        data.put("generated", demoService.generateGasDemo(day));
        return AjaxResult.success(data);
    }
 
    private Map<String, Object> runResult(Long runId) {
        Map<String, Object> data = new LinkedHashMap<>();
        data.put("runId", runId);
        return data;
    }
 
    private LocalDate parseDate(String value) {
        if (StringUtils.isBlank(value)) {
            return null;
        }
        try {
            return LocalDate.parse(value.trim());
        } catch (Exception e) {
            throw new ServiceException("日期格式应为 yyyy-MM-dd");
        }
    }
}