|
1
|
1
|
package com.iot.scheduler.service;
|
|
2
|
2
|
|
|
|
3
|
+import com.alibaba.fastjson.JSON;
|
|
|
4
|
+import com.alibaba.fastjson.JSONArray;
|
|
|
5
|
+import com.alibaba.fastjson.JSONObject;
|
|
3
|
6
|
import lombok.extern.slf4j.Slf4j;
|
|
4
|
7
|
import org.springframework.beans.factory.annotation.Value;
|
|
5
|
8
|
import org.springframework.jdbc.core.JdbcTemplate;
|
|
...
|
...
|
@@ -8,6 +11,8 @@ import org.springframework.util.StringUtils; |
|
8
|
11
|
|
|
9
|
12
|
import jakarta.annotation.Resource;
|
|
10
|
13
|
|
|
|
14
|
+import java.math.BigDecimal;
|
|
|
15
|
+import java.math.RoundingMode;
|
|
11
|
16
|
import java.util.*;
|
|
12
|
17
|
|
|
13
|
18
|
@Slf4j
|
|
...
|
...
|
@@ -18,6 +23,10 @@ public class EnergySearchService { |
|
18
|
23
|
private String energyCorpCode;
|
|
19
|
24
|
@Value("${energy.db.tableName}")
|
|
20
|
25
|
private String energyTableName;
|
|
|
26
|
+ @Value("${energy.db.eqKwhTableName}")
|
|
|
27
|
+ private String eqKwhTableName;
|
|
|
28
|
+ @Value("${energy.db.eRunDtlTableName}")
|
|
|
29
|
+ private String eRunDtlTableName;
|
|
21
|
30
|
|
|
22
|
31
|
@Resource
|
|
23
|
32
|
private JdbcTemplate jdbcTemplate;
|
|
...
|
...
|
@@ -120,4 +129,124 @@ public class EnergySearchService { |
|
120
|
129
|
"3", statusMap.get("3")
|
|
121
|
130
|
);
|
|
122
|
131
|
}
|
|
|
132
|
+
|
|
|
133
|
+ /**
|
|
|
134
|
+ * 根据dtuSn查询指定日期的设备时用电量和OEE时序
|
|
|
135
|
+ * 1. 时用电量:从t_auto_ymk_iot_eq_kwh表获取,并计算当日总用电量
|
|
|
136
|
+ * 2. OEE时序:从t_auto_ymk_iot_e_run_dtl表获取,统计总时长、各状态运行时长和占比
|
|
|
137
|
+ *
|
|
|
138
|
+ * @param dtuSn 设备序列号
|
|
|
139
|
+ * @param date 查询日期 yyyy-MM-dd
|
|
|
140
|
+ */
|
|
|
141
|
+ public Map<String, Object> queryEnergyDetailByDate(String dtuSn, String date) {
|
|
|
142
|
+ // 1. 查询时用电量数据 - 原始数据直接返回
|
|
|
143
|
+ Object kwhRawData = Collections.emptyList();
|
|
|
144
|
+ BigDecimal totalKwh = BigDecimal.ZERO;
|
|
|
145
|
+ try {
|
|
|
146
|
+ String kwhSql = "SELECT description FROM " + eqKwhTableName
|
|
|
147
|
+ + " WHERE corp_code = ? AND dtuSn = ? AND use_date = ?";
|
|
|
148
|
+ Map<String, Object> kwhRow = jdbcTemplate.queryForMap(kwhSql, energyCorpCode, dtuSn, date + " 00:00:00");
|
|
|
149
|
+ if (kwhRow != null && kwhRow.get("description") != null) {
|
|
|
150
|
+ String description = String.valueOf(kwhRow.get("description"));
|
|
|
151
|
+ kwhRawData = JSON.parseArray(description);
|
|
|
152
|
+ // 计算总用电量
|
|
|
153
|
+ JSONArray dataArray = JSON.parseArray(description);
|
|
|
154
|
+ for (int i = 0; i < dataArray.size(); i++) {
|
|
|
155
|
+ JSONObject item = dataArray.getJSONObject(i);
|
|
|
156
|
+ Double value = item.getDouble("value");
|
|
|
157
|
+ if (value != null) {
|
|
|
158
|
+ totalKwh = totalKwh.add(BigDecimal.valueOf(value));
|
|
|
159
|
+ }
|
|
|
160
|
+ }
|
|
|
161
|
+ }
|
|
|
162
|
+ } catch (Exception e) {
|
|
|
163
|
+ log.warn("【能耗明细】查询时用电量数据为空或异常 - dtuSn:{}, date:{}", dtuSn, date);
|
|
|
164
|
+ }
|
|
|
165
|
+
|
|
|
166
|
+ // 2. 查询OEE时序数据 - 原始数据直接返回
|
|
|
167
|
+ Object oeeRawData = Collections.emptyList();
|
|
|
168
|
+ long totalDuration = 0;
|
|
|
169
|
+ // runStatus状态: 0-离线, 1-停机, 2-待机, 3-运行
|
|
|
170
|
+ Map<Integer, Long> statusDurationMap = new LinkedHashMap<>();
|
|
|
171
|
+ statusDurationMap.put(0, 0L); // 离线
|
|
|
172
|
+ statusDurationMap.put(1, 0L); // 停机
|
|
|
173
|
+ statusDurationMap.put(2, 0L); // 待机
|
|
|
174
|
+ statusDurationMap.put(3, 0L); // 运行
|
|
|
175
|
+
|
|
|
176
|
+ try {
|
|
|
177
|
+ String oeeSql = "SELECT runStatus1, runStatus2 FROM " + eRunDtlTableName
|
|
|
178
|
+ + " WHERE corp_code = ? AND dtuSn = ? AND use_date = ?";
|
|
|
179
|
+ Map<String, Object> oeeRow = jdbcTemplate.queryForMap(oeeSql, energyCorpCode, dtuSn, date + " 00:00:00");
|
|
|
180
|
+ if (oeeRow != null) {
|
|
|
181
|
+ String rs1 = oeeRow.get("runStatus1") != null ? String.valueOf(oeeRow.get("runStatus1")) : "";
|
|
|
182
|
+ String rs2 = oeeRow.get("runStatus2") != null ? String.valueOf(oeeRow.get("runStatus2")) : "";
|
|
|
183
|
+ String jsonStr = rs1 + rs2;
|
|
|
184
|
+ oeeRawData = JSON.parseArray(jsonStr);
|
|
|
185
|
+
|
|
|
186
|
+ // 统计各状态时长
|
|
|
187
|
+ JSONArray dataArray = JSON.parseArray(jsonStr);
|
|
|
188
|
+ for (int i = 0; i < dataArray.size(); i++) {
|
|
|
189
|
+ JSONObject item = dataArray.getJSONObject(i);
|
|
|
190
|
+ Long duration = item.getLong("duration");
|
|
|
191
|
+ Integer runStatus = item.getInteger("runStatus");
|
|
|
192
|
+
|
|
|
193
|
+ if (duration != null && duration > 0) {
|
|
|
194
|
+ totalDuration += duration;
|
|
|
195
|
+ int statusKey = runStatus != null ? runStatus : 0;
|
|
|
196
|
+ statusDurationMap.merge(statusKey, duration, Long::sum);
|
|
|
197
|
+ }
|
|
|
198
|
+ }
|
|
|
199
|
+ }
|
|
|
200
|
+ } catch (Exception e) {
|
|
|
201
|
+ log.warn("【能耗明细】查询OEE时序数据为空或异常 - dtuSn:{}, date:{}", dtuSn, date);
|
|
|
202
|
+ }
|
|
|
203
|
+
|
|
|
204
|
+ // 3. 构建OEE统计结果(含格式化时长和占比)
|
|
|
205
|
+ List<Map<String, Object>> statusStats = new ArrayList<>();
|
|
|
206
|
+ for (Map.Entry<Integer, Long> entry : statusDurationMap.entrySet()) {
|
|
|
207
|
+ long dur = entry.getValue();
|
|
|
208
|
+ double percent = totalDuration > 0 ? BigDecimal.valueOf(dur * 100.0 / totalDuration)
|
|
|
209
|
+ .setScale(2, RoundingMode.HALF_UP).doubleValue() : 0.0;
|
|
|
210
|
+
|
|
|
211
|
+ Map<String, Object> stat = new LinkedHashMap<>();
|
|
|
212
|
+ stat.put("status", entry.getKey());
|
|
|
213
|
+ stat.put("durationSeconds", dur);
|
|
|
214
|
+ stat.put("durationFormatted", formatDuration(dur));
|
|
|
215
|
+ stat.put("percent", percent);
|
|
|
216
|
+ statusStats.add(stat);
|
|
|
217
|
+ }
|
|
|
218
|
+
|
|
|
219
|
+ return Map.of(
|
|
|
220
|
+ "code", 200,
|
|
|
221
|
+ "msg", "请求成功",
|
|
|
222
|
+ "dtuSn", dtuSn,
|
|
|
223
|
+ "date", date,
|
|
|
224
|
+ "kwhData", Map.of(
|
|
|
225
|
+ "list", kwhRawData,
|
|
|
226
|
+ "totalKwh", totalKwh.setScale(2, RoundingMode.HALF_UP)
|
|
|
227
|
+ ),
|
|
|
228
|
+ "oeeData", Map.of(
|
|
|
229
|
+ "list", oeeRawData,
|
|
|
230
|
+ "totalDurationFormatted", formatDuration(totalDuration),
|
|
|
231
|
+ "totalDurationSeconds", totalDuration,
|
|
|
232
|
+ "statusStats", statusStats
|
|
|
233
|
+ )
|
|
|
234
|
+ );
|
|
|
235
|
+ }
|
|
|
236
|
+
|
|
|
237
|
+ /**
|
|
|
238
|
+ * 格式化时长为 xx时xx分xx秒 格式
|
|
|
239
|
+ * 时不为0则展示xx时xx分xx秒
|
|
|
240
|
+ * 时和分都为0则只展示xx秒
|
|
|
241
|
+ */
|
|
|
242
|
+ private static String formatDuration(long totalSeconds) {
|
|
|
243
|
+ long h = totalSeconds / 3600;
|
|
|
244
|
+ long m = (totalSeconds % 3600) / 60;
|
|
|
245
|
+ long s = totalSeconds % 60;
|
|
|
246
|
+ StringBuilder sb = new StringBuilder();
|
|
|
247
|
+ if (h > 0) sb.append(h).append("时");
|
|
|
248
|
+ if (h > 0 || m > 0) sb.append(m).append("分");
|
|
|
249
|
+ sb.append(s).append("秒");
|
|
|
250
|
+ return sb.toString();
|
|
|
251
|
+ }
|
|
123
|
252
|
} |
...
|
...
|
|