|
@@ -80,8 +80,11 @@ public class PjDeviceReportService { |
|
@@ -80,8 +80,11 @@ public class PjDeviceReportService { |
|
80
|
@Value("${pj.third.energyFormId:t6937bc62e4332f00072a0849}")
|
80
|
@Value("${pj.third.energyFormId:t6937bc62e4332f00072a0849}")
|
|
81
|
private String energyFormId;
|
81
|
private String energyFormId;
|
|
82
|
|
82
|
|
|
83
|
- @Value("${pj.third.selectEnergySql:SELECT * FROM ts_kv_dictionary;}")
|
|
|
|
84
|
- private String selectEnergySql;
|
83
|
+ @Value("${pj.third.selectJinHongEnergySql:SELECT * FROM ts_kv_dictionary;}")
|
|
|
|
84
|
+ private String selectJinHongEnergySql;
|
|
|
|
85
|
+
|
|
|
|
86
|
+ @Value("${pj.third.selectZongJianCaiEnergySql:SELECT * FROM ts_kv_dictionary;}")
|
|
|
|
87
|
+ private String selectZongJianCaiEnergySql;
|
|
85
|
|
88
|
|
|
86
|
@Resource
|
89
|
@Resource
|
|
87
|
private RedisTemplate<String, String> redisTemplate;
|
90
|
private RedisTemplate<String, String> redisTemplate;
|
|
@@ -250,16 +253,16 @@ public class PjDeviceReportService { |
|
@@ -250,16 +253,16 @@ public class PjDeviceReportService { |
|
250
|
}
|
253
|
}
|
|
251
|
|
254
|
|
|
252
|
/**
|
255
|
/**
|
|
253
|
- * 企业设备能耗上报
|
256
|
+ * 金宏能耗上报
|
|
254
|
*/
|
257
|
*/
|
|
255
|
- public void batchReportEnergyEnterprise() {
|
258
|
+ public void reportJinHongEnergy() {
|
|
256
|
log.info("开始执行企业设备能耗上报任务");
|
259
|
log.info("开始执行企业设备能耗上报任务");
|
|
257
|
long startTime = System.currentTimeMillis();
|
260
|
long startTime = System.currentTimeMillis();
|
|
258
|
|
261
|
|
|
259
|
try {
|
262
|
try {
|
|
260
|
// 1. 查询需要同步的数据
|
263
|
// 1. 查询需要同步的数据
|
|
261
|
log.info("步骤1: 开始查询需要同步的设备数据");
|
264
|
log.info("步骤1: 开始查询需要同步的设备数据");
|
|
262
|
- List<Object> needSyncDataList = initConnectAndSelectData2();
|
265
|
+ List<Object> needSyncDataList = initJinHongConnectAndSelectData();
|
|
263
|
|
266
|
|
|
264
|
if (CollectionUtils.isEmpty(needSyncDataList)) {
|
267
|
if (CollectionUtils.isEmpty(needSyncDataList)) {
|
|
265
|
log.info("未查询到需要同步的设备数据,任务结束");
|
268
|
log.info("未查询到需要同步的设备数据,任务结束");
|
|
@@ -416,6 +419,162 @@ public class PjDeviceReportService { |
|
@@ -416,6 +419,162 @@ public class PjDeviceReportService { |
|
416
|
}
|
419
|
}
|
|
417
|
}
|
420
|
}
|
|
418
|
|
421
|
|
|
|
|
422
|
+ /**
|
|
|
|
423
|
+ * 金宏能耗上报
|
|
|
|
424
|
+ */
|
|
|
|
425
|
+ public void reportZongJianCaiEnergy() {
|
|
|
|
426
|
+ log.info("开始执行企业设备能耗上报任务");
|
|
|
|
427
|
+ long startTime = System.currentTimeMillis();
|
|
|
|
428
|
+
|
|
|
|
429
|
+ try {
|
|
|
|
430
|
+ // 1. 查询需要同步的数据
|
|
|
|
431
|
+ log.info("步骤1: 开始查询需要同步的设备数据");
|
|
|
|
432
|
+ List<Object> needSyncDataList = initZongJianCaiConnectAndSelectData();
|
|
|
|
433
|
+
|
|
|
|
434
|
+ if (CollectionUtils.isEmpty(needSyncDataList)) {
|
|
|
|
435
|
+ log.info("未查询到需要同步的设备数据,任务结束");
|
|
|
|
436
|
+ return;
|
|
|
|
437
|
+ }
|
|
|
|
438
|
+
|
|
|
|
439
|
+ log.info("共查询到 {} 条设备数据需要同步", needSyncDataList.size());
|
|
|
|
440
|
+
|
|
|
|
441
|
+ // 2. 准备上报数据
|
|
|
|
442
|
+ log.info("步骤2: 开始准备上报数据");
|
|
|
|
443
|
+
|
|
|
|
444
|
+ CloseableHttpClient httpclient = HttpClients.createDefault();
|
|
|
|
445
|
+ HttpPost httpPost = new HttpPost(reportUrl);
|
|
|
|
446
|
+
|
|
|
|
447
|
+ // 3. 获取并设置Token
|
|
|
|
448
|
+ log.info("步骤3: 获取访问令牌");
|
|
|
|
449
|
+ String token = getTokenNoCache();
|
|
|
|
450
|
+ if (StringUtils.isBlank(token)) {
|
|
|
|
451
|
+ log.error("获取访问令牌失败,无法进行数据上报");
|
|
|
|
452
|
+ return;
|
|
|
|
453
|
+ }
|
|
|
|
454
|
+
|
|
|
|
455
|
+ httpPost.setHeader("Authorization", "Bearer " + token);
|
|
|
|
456
|
+ httpPost.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
|
|
457
|
+ log.info("请求URL: {}, Token已设置", reportUrl);
|
|
|
|
458
|
+
|
|
|
|
459
|
+ // 4. 构建上报数据
|
|
|
|
460
|
+ log.info("步骤4: 构建上报数据结构");
|
|
|
|
461
|
+ List<Map<String, Object>> dataList = new ArrayList<>(needSyncDataList.size());
|
|
|
|
462
|
+ List<Map<String, Object>> saveDataList = new ArrayList<>(needSyncDataList.size());
|
|
|
|
463
|
+ int successCount = 0;
|
|
|
|
464
|
+ int errorCount = 0;
|
|
|
|
465
|
+ DeviceDataStorage storage = new DeviceDataStorage();
|
|
|
|
466
|
+ for (int i = 0; i < needSyncDataList.size(); i++) {
|
|
|
|
467
|
+ try {
|
|
|
|
468
|
+ Object needSyncData = needSyncDataList.get(i);
|
|
|
|
469
|
+ List<Object> dataObject = (ArrayList) needSyncData;
|
|
|
|
470
|
+
|
|
|
|
471
|
+ if (dataObject.size() < 4) {
|
|
|
|
472
|
+ log.warn("第 {} 条数据格式不正确,期望至少4个字段,实际: {}", i + 1, dataObject.size());
|
|
|
|
473
|
+ errorCount++;
|
|
|
|
474
|
+ continue;
|
|
|
|
475
|
+ }
|
|
|
|
476
|
+
|
|
|
|
477
|
+ Map<String, Object> data = new HashMap<>();
|
|
|
|
478
|
+ String deviceCode = (String) dataObject.get(2);
|
|
|
|
479
|
+ String energyType = (String) dataObject.get(3);
|
|
|
|
480
|
+
|
|
|
|
481
|
+ data.put("entName", dataObject.get(0));
|
|
|
|
482
|
+ data.put("deviceName", dataObject.get(1));
|
|
|
|
483
|
+ data.put("deviceCode", deviceCode);
|
|
|
|
484
|
+ data.put("energyType", energyType);
|
|
|
|
485
|
+ Long ts = (Long) dataObject.get(5);
|
|
|
|
486
|
+ DeviceDataStorage.DeviceRecord lastRecord = storage.getLastRecord(deviceCode);
|
|
|
|
487
|
+ if (lastRecord == null) {
|
|
|
|
488
|
+ log.warn("第 {} 条数据,设备:{} 未找到上一期上报数据", i + 1, deviceCode);
|
|
|
|
489
|
+ continue;
|
|
|
|
490
|
+ }
|
|
|
|
491
|
+ if (lastRecord.getTimestamp() >= ts) {
|
|
|
|
492
|
+ log.warn("第 {} 条数据,设备:{} 数据未更新无需上报", i + 1, deviceCode);
|
|
|
|
493
|
+ continue;
|
|
|
|
494
|
+ }
|
|
|
|
495
|
+ Double energyValue = toDouble(dataObject.get(4));
|
|
|
|
496
|
+
|
|
|
|
497
|
+ if ("电".equals(energyType) || "天然气".equals(energyType)|| "水".equals(energyType)) {
|
|
|
|
498
|
+ data.put("energyValue", energyValue);
|
|
|
|
499
|
+ data.put("timeSpan", "日");
|
|
|
|
500
|
+ data.put("collectTime", toYyyyMmDd(ts));
|
|
|
|
501
|
+ } else {
|
|
|
|
502
|
+ log.warn("第 {} 条数据,设备:{} 物模型数据错误!", i + 1, deviceCode);
|
|
|
|
503
|
+ continue;
|
|
|
|
504
|
+ }
|
|
|
|
505
|
+
|
|
|
|
506
|
+ dataList.add(data);
|
|
|
|
507
|
+ Map<String, Object> saveData = (Map<String, Object>) SerializationUtils.clone((Serializable) data);
|
|
|
|
508
|
+ saveData.put("ts",ts);
|
|
|
|
509
|
+ saveData.put("orignValue",energyValue);
|
|
|
|
510
|
+ saveDataList.add(saveData);
|
|
|
|
511
|
+
|
|
|
|
512
|
+ successCount++;
|
|
|
|
513
|
+
|
|
|
|
514
|
+ // 每100条记录输出一次进度
|
|
|
|
515
|
+ if (successCount % 100 == 0) {
|
|
|
|
516
|
+ log.info("已成功构建 {} 条上报数据", successCount);
|
|
|
|
517
|
+ }
|
|
|
|
518
|
+
|
|
|
|
519
|
+ } catch (Exception e) {
|
|
|
|
520
|
+ log.error("处理第 {} 条数据时发生异常", i + 1, e);
|
|
|
|
521
|
+ errorCount++;
|
|
|
|
522
|
+ }
|
|
|
|
523
|
+ }
|
|
|
|
524
|
+
|
|
|
|
525
|
+ log.info("数据构建完成,成功: {} 条,失败: {} 条", successCount, errorCount);
|
|
|
|
526
|
+
|
|
|
|
527
|
+ if (CollectionUtils.isEmpty(dataList)) {
|
|
|
|
528
|
+ log.error("没有成功构建任何上报数据,任务结束");
|
|
|
|
529
|
+ return;
|
|
|
|
530
|
+ }
|
|
|
|
531
|
+
|
|
|
|
532
|
+ // 5. 构建请求体
|
|
|
|
533
|
+ log.info("步骤5: 构建请求体");
|
|
|
|
534
|
+ Map<String, Object> sendData = new HashMap<>(3);
|
|
|
|
535
|
+ sendData.put("formId", energyFormId);
|
|
|
|
536
|
+ List<String> uniqueKeyList = Arrays.asList(energyUniqueKeys.split(","));
|
|
|
|
537
|
+ sendData.put("uniqueKeys", uniqueKeyList);
|
|
|
|
538
|
+ sendData.put("datas", dataList);
|
|
|
|
539
|
+
|
|
|
|
540
|
+ String json = JSON.toJSONString(sendData);
|
|
|
|
541
|
+ log.debug("请求体JSON数据: {}", json);
|
|
|
|
542
|
+ log.info("请求体大小: {} 字符", json.length());
|
|
|
|
543
|
+
|
|
|
|
544
|
+ httpPost.setEntity(new StringEntity(json, StandardCharsets.UTF_8));
|
|
|
|
545
|
+
|
|
|
|
546
|
+ // 6. 发送请求
|
|
|
|
547
|
+ log.info("步骤6: 发送HTTP请求到第三方平台");
|
|
|
|
548
|
+ try (CloseableHttpResponse response = httpclient.execute(httpPost)) {
|
|
|
|
549
|
+ int statusCode = response.getStatusLine().getStatusCode();
|
|
|
|
550
|
+ String result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
|
|
|
|
551
|
+
|
|
|
|
552
|
+ log.info("HTTP响应状态码: {}", statusCode);
|
|
|
|
553
|
+ log.info("HTTP响应内容: {}", result);
|
|
|
|
554
|
+
|
|
|
|
555
|
+ if (statusCode == 200) {
|
|
|
|
556
|
+ JSONObject jsonResult = JSON.parseObject(result);
|
|
|
|
557
|
+ if (jsonResult != null && "true".equalsIgnoreCase(jsonResult.getString("success"))) {
|
|
|
|
558
|
+ log.info("数据上报成功!共上报 {} 条设备数据", dataList.size());
|
|
|
|
559
|
+ //记录上报数据
|
|
|
|
560
|
+ saveReportData(saveDataList);
|
|
|
|
561
|
+ } else {
|
|
|
|
562
|
+ log.error("数据上报失败!响应状态异常: {}", result);
|
|
|
|
563
|
+ }
|
|
|
|
564
|
+ } else {
|
|
|
|
565
|
+ log.error("HTTP请求失败,状态码: {}", statusCode);
|
|
|
|
566
|
+ }
|
|
|
|
567
|
+
|
|
|
|
568
|
+ } catch (Exception e) {
|
|
|
|
569
|
+ log.error("发送HTTP请求时发生异常", e);
|
|
|
|
570
|
+ }
|
|
|
|
571
|
+
|
|
|
|
572
|
+ } finally {
|
|
|
|
573
|
+ long endTime = System.currentTimeMillis();
|
|
|
|
574
|
+ log.info("企业设备能耗上报任务执行完成,总耗时: {} 毫秒", (endTime - startTime));
|
|
|
|
575
|
+ }
|
|
|
|
576
|
+ }
|
|
|
|
577
|
+
|
|
419
|
private void saveReportData(List<Map<String, Object>> dataList) {
|
578
|
private void saveReportData(List<Map<String, Object>> dataList) {
|
|
420
|
if (CollectionUtils.isEmpty(dataList)) {
|
579
|
if (CollectionUtils.isEmpty(dataList)) {
|
|
421
|
return;
|
580
|
return;
|
|
@@ -654,7 +813,90 @@ public class PjDeviceReportService { |
|
@@ -654,7 +813,90 @@ public class PjDeviceReportService { |
|
654
|
return resultList;
|
813
|
return resultList;
|
|
655
|
}
|
814
|
}
|
|
656
|
|
815
|
|
|
657
|
- private List<Object> initConnectAndSelectData2() {
|
816
|
+ private List<Object> initJinHongConnectAndSelectData() {
|
|
|
|
817
|
+ Connection connection = null;
|
|
|
|
818
|
+ PreparedStatement statement = null;
|
|
|
|
819
|
+ ResultSet resultSet = null;
|
|
|
|
820
|
+ HikariDataSource dataSource = null;
|
|
|
|
821
|
+ List<Object> resultList = new ArrayList<>();
|
|
|
|
822
|
+
|
|
|
|
823
|
+ log.info("开始连接数据库,URL: {}", jdbcUrl);
|
|
|
|
824
|
+
|
|
|
|
825
|
+ try {
|
|
|
|
826
|
+ HikariConfig config = new HikariConfig();
|
|
|
|
827
|
+ config.setJdbcUrl(jdbcUrl);
|
|
|
|
828
|
+ config.setUsername(jdbcUserName);
|
|
|
|
829
|
+ config.setPassword(jdbcPassword);
|
|
|
|
830
|
+ config.setDriverClassName("org.postgresql.Driver");
|
|
|
|
831
|
+ config.setMaximumPoolSize(5);
|
|
|
|
832
|
+ config.setMinimumIdle(5);
|
|
|
|
833
|
+ config.setConnectionTimeout(60000);
|
|
|
|
834
|
+ config.setConnectionTestQuery("SELECT 1");
|
|
|
|
835
|
+
|
|
|
|
836
|
+ dataSource = new HikariDataSource(config);
|
|
|
|
837
|
+ log.info("Hikari连接池配置完成");
|
|
|
|
838
|
+
|
|
|
|
839
|
+ connection = dataSource.getConnection();
|
|
|
|
840
|
+ log.info("数据库连接成功");
|
|
|
|
841
|
+
|
|
|
|
842
|
+ statement = connection.prepareStatement(selectJinHongEnergySql);
|
|
|
|
843
|
+ log.info("执行SQL查询: {}", selectSql);
|
|
|
|
844
|
+
|
|
|
|
845
|
+ resultSet = statement.executeQuery();
|
|
|
|
846
|
+ ResultSetMetaData metaData = resultSet.getMetaData();
|
|
|
|
847
|
+ int columnCount = metaData.getColumnCount();
|
|
|
|
848
|
+ log.info("查询结果集元数据获取成功,共{}列", columnCount);
|
|
|
|
849
|
+
|
|
|
|
850
|
+ int rowCount = 0;
|
|
|
|
851
|
+ while (resultSet.next()) {
|
|
|
|
852
|
+ List<Object> result = new ArrayList<>(columnCount);
|
|
|
|
853
|
+ for (int index = 1; index <= columnCount; index++) {
|
|
|
|
854
|
+ int columnType = metaData.getColumnType(index);
|
|
|
|
855
|
+ Object value = getTypedValue(resultSet, index, columnType);
|
|
|
|
856
|
+ result.add(value);
|
|
|
|
857
|
+ }
|
|
|
|
858
|
+ resultList.add(result);
|
|
|
|
859
|
+ rowCount++;
|
|
|
|
860
|
+
|
|
|
|
861
|
+ // 每处理1000行记录一次日志
|
|
|
|
862
|
+ if (rowCount % 1000 == 0) {
|
|
|
|
863
|
+ log.info("已处理{}行数据", rowCount);
|
|
|
|
864
|
+ }
|
|
|
|
865
|
+ }
|
|
|
|
866
|
+
|
|
|
|
867
|
+ log.info("数据查询完成,共获取{}行数据", rowCount);
|
|
|
|
868
|
+
|
|
|
|
869
|
+ } catch (SQLException e) {
|
|
|
|
870
|
+ log.error("数据库操作异常,URL: {}, 用户名: {}", jdbcUrl, jdbcUserName, e);
|
|
|
|
871
|
+ } catch (Exception e) {
|
|
|
|
872
|
+ log.error("初始化数据库连接或查询数据时发生异常", e);
|
|
|
|
873
|
+ } finally {
|
|
|
|
874
|
+ // 释放资源
|
|
|
|
875
|
+ try {
|
|
|
|
876
|
+ if (resultSet != null) resultSet.close();
|
|
|
|
877
|
+ if (statement != null) statement.close();
|
|
|
|
878
|
+ if (connection != null) connection.close();
|
|
|
|
879
|
+ log.info("数据库连接资源已释放");
|
|
|
|
880
|
+ } catch (SQLException e) {
|
|
|
|
881
|
+ log.error("关闭数据库资源时发生异常", e);
|
|
|
|
882
|
+ }
|
|
|
|
883
|
+
|
|
|
|
884
|
+ if (dataSource != null) {
|
|
|
|
885
|
+ try {
|
|
|
|
886
|
+ dataSource.close();
|
|
|
|
887
|
+ log.info("HikariDataSource连接池已关闭");
|
|
|
|
888
|
+ } catch (Exception e) {
|
|
|
|
889
|
+ log.error("关闭HikariDataSource连接池时发生异常", e);
|
|
|
|
890
|
+ }
|
|
|
|
891
|
+ }
|
|
|
|
892
|
+ }
|
|
|
|
893
|
+
|
|
|
|
894
|
+ log.info("数据库操作完成,返回{}条记录", resultList.size());
|
|
|
|
895
|
+ return resultList;
|
|
|
|
896
|
+ }
|
|
|
|
897
|
+
|
|
|
|
898
|
+
|
|
|
|
899
|
+ private List<Object> initZongJianCaiConnectAndSelectData() {
|
|
658
|
Connection connection = null;
|
900
|
Connection connection = null;
|
|
659
|
PreparedStatement statement = null;
|
901
|
PreparedStatement statement = null;
|
|
660
|
ResultSet resultSet = null;
|
902
|
ResultSet resultSet = null;
|
|
@@ -680,7 +922,7 @@ public class PjDeviceReportService { |
|
@@ -680,7 +922,7 @@ public class PjDeviceReportService { |
|
680
|
connection = dataSource.getConnection();
|
922
|
connection = dataSource.getConnection();
|
|
681
|
log.info("数据库连接成功");
|
923
|
log.info("数据库连接成功");
|
|
682
|
|
924
|
|
|
683
|
- statement = connection.prepareStatement(selectEnergySql);
|
925
|
+ statement = connection.prepareStatement(selectZongJianCaiEnergySql);
|
|
684
|
log.info("执行SQL查询: {}", selectSql);
|
926
|
log.info("执行SQL查询: {}", selectSql);
|
|
685
|
|
927
|
|
|
686
|
resultSet = statement.executeQuery();
|
928
|
resultSet = statement.executeQuery();
|