Commit 7f2e7d1b63ceb065912bddc8a351e9ab59f06720

Authored by 胡翰林
1 parent cca313a1

潘集设备上报

@@ -67,6 +67,15 @@ public class PjDeviceReportService { @@ -67,6 +67,15 @@ public class PjDeviceReportService {
67 @Value("${pj.third.selectSql:SELECT * FROM ts_kv_dictionary;}") 67 @Value("${pj.third.selectSql:SELECT * FROM ts_kv_dictionary;}")
68 private String selectSql; 68 private String selectSql;
69 69
  70 + @Value("${pj.third.energyUniqueKeys:entName,deviceCode}")
  71 + private String energyUniqueKeys;
  72 +
  73 + @Value("${pj.third.energyFormId:t6937bc62e4332f00072a0849}")
  74 + private String energyFormId;
  75 +
  76 + @Value("${pj.third.selectEnergySql:SELECT * FROM ts_kv_dictionary;}")
  77 + private String selectEnergySql;
  78 +
70 @Resource 79 @Resource
71 private RedisTemplate<String, String> redisTemplate; 80 private RedisTemplate<String, String> redisTemplate;
72 81
@@ -215,6 +224,136 @@ public class PjDeviceReportService { @@ -215,6 +224,136 @@ public class PjDeviceReportService {
215 } 224 }
216 225
217 /** 226 /**
  227 + * 企业设备能耗上报
  228 + */
  229 + public void batchReportEnergyEnterprise() {
  230 + log.info("开始执行企业设备能耗上报任务");
  231 + long startTime = System.currentTimeMillis();
  232 +
  233 + try {
  234 + // 1. 查询需要同步的数据
  235 + log.info("步骤1: 开始查询需要同步的设备数据");
  236 + List<Object> needSyncDataList = initConnectAndSelectData2();
  237 +
  238 + if (CollectionUtils.isEmpty(needSyncDataList)) {
  239 + log.info("未查询到需要同步的设备数据,任务结束");
  240 + return;
  241 + }
  242 +
  243 + log.info("共查询到 {} 条设备数据需要同步", needSyncDataList.size());
  244 +
  245 + // 2. 准备上报数据
  246 + log.info("步骤2: 开始准备上报数据");
  247 + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
  248 + String nowTime = simpleDateFormat.format(new java.util.Date());
  249 + log.info("上报时间: {}", nowTime);
  250 +
  251 + CloseableHttpClient httpclient = HttpClients.createDefault();
  252 + HttpPost httpPost = new HttpPost(reportUrl);
  253 +
  254 + // 3. 获取并设置Token
  255 + log.info("步骤3: 获取访问令牌");
  256 + String token = getToken();
  257 + if (StringUtils.isBlank(token)) {
  258 + log.error("获取访问令牌失败,无法进行数据上报");
  259 + return;
  260 + }
  261 +
  262 + httpPost.setHeader("Authorization", "Bearer " + token);
  263 + httpPost.setHeader("Content-Type", "application/json; charset=utf-8");
  264 + log.info("请求URL: {}, Token已设置", reportUrl);
  265 +
  266 + // 4. 构建上报数据
  267 + log.info("步骤4: 构建上报数据结构");
  268 + List<Map<String, Object>> dataList = new ArrayList<>(needSyncDataList.size());
  269 + int successCount = 0;
  270 + int errorCount = 0;
  271 +
  272 + for (int i = 0; i < needSyncDataList.size(); i++) {
  273 + try {
  274 + Object needSyncData = needSyncDataList.get(i);
  275 + List<Object> dataObject = (ArrayList) needSyncData;
  276 +
  277 + if (dataObject.size() < 4) {
  278 + log.warn("第 {} 条数据格式不正确,期望至少4个字段,实际: {}", i + 1, dataObject.size());
  279 + errorCount++;
  280 + continue;
  281 + }
  282 +
  283 + Map<String, Object> data = new HashMap<>();
  284 + data.put("entName", dataObject.get(0));
  285 + data.put("deviceName", dataObject.get(1));
  286 + data.put("deviceCode", dataObject.get(2));
  287 + data.put("energyType", dataObject.get(3));
  288 + data.put("energyValue", dataObject.get(4));
  289 + data.put("timeSpan", "日");
  290 + data.put("collectTime", nowTime);
  291 + dataList.add(data);
  292 + successCount++;
  293 +
  294 + // 每100条记录输出一次进度
  295 + if (successCount % 100 == 0) {
  296 + log.info("已成功构建 {} 条上报数据", successCount);
  297 + }
  298 +
  299 + } catch (Exception e) {
  300 + log.error("处理第 {} 条数据时发生异常", i + 1, e);
  301 + errorCount++;
  302 + }
  303 + }
  304 +
  305 + log.info("数据构建完成,成功: {} 条,失败: {} 条", successCount, errorCount);
  306 +
  307 + if (CollectionUtils.isEmpty(dataList)) {
  308 + log.error("没有成功构建任何上报数据,任务结束");
  309 + return;
  310 + }
  311 +
  312 + // 5. 构建请求体
  313 + log.info("步骤5: 构建请求体");
  314 + Map<String, Object> sendData = new HashMap<>(3);
  315 + sendData.put("formId", energyFormId);
  316 + List<String> uniqueKeyList = Arrays.asList(energyUniqueKeys.split(","));
  317 + sendData.put("uniqueKeys", uniqueKeyList);
  318 + sendData.put("datas", dataList);
  319 +
  320 + String json = JSON.toJSONString(sendData);
  321 + log.debug("请求体JSON数据: {}", json);
  322 + log.info("请求体大小: {} 字符", json.length());
  323 +
  324 + httpPost.setEntity(new StringEntity(json, StandardCharsets.UTF_8));
  325 +
  326 + // 6. 发送请求
  327 + log.info("步骤6: 发送HTTP请求到第三方平台");
  328 + try (CloseableHttpResponse response = httpclient.execute(httpPost)) {
  329 + int statusCode = response.getStatusLine().getStatusCode();
  330 + String result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
  331 +
  332 + log.info("HTTP响应状态码: {}", statusCode);
  333 + log.info("HTTP响应内容: {}", result);
  334 +
  335 + if (statusCode == 200) {
  336 + JSONObject jsonResult = JSON.parseObject(result);
  337 + if (jsonResult != null && "true".equalsIgnoreCase(jsonResult.getString("success"))) {
  338 + log.info("数据上报成功!共上报 {} 条设备数据", dataList.size());
  339 + } else {
  340 + log.error("数据上报失败!响应状态异常: {}", result);
  341 + }
  342 + } else {
  343 + log.error("HTTP请求失败,状态码: {}", statusCode);
  344 + }
  345 +
  346 + } catch (Exception e) {
  347 + log.error("发送HTTP请求时发生异常", e);
  348 + }
  349 +
  350 + } finally {
  351 + long endTime = System.currentTimeMillis();
  352 + log.info("企业设备能耗上报任务执行完成,总耗时: {} 毫秒", (endTime - startTime));
  353 + }
  354 + }
  355 +
  356 + /**
218 * 获取token 357 * 获取token
219 * 358 *
220 * @return 359 * @return
@@ -375,6 +514,88 @@ public class PjDeviceReportService { @@ -375,6 +514,88 @@ public class PjDeviceReportService {
375 return resultList; 514 return resultList;
376 } 515 }
377 516
  517 + private List<Object> initConnectAndSelectData2() {
  518 + Connection connection = null;
  519 + PreparedStatement statement = null;
  520 + ResultSet resultSet = null;
  521 + HikariDataSource dataSource = null;
  522 + List<Object> resultList = new ArrayList<>();
  523 +
  524 + log.info("开始连接数据库,URL: {}", jdbcUrl);
  525 +
  526 + try {
  527 + HikariConfig config = new HikariConfig();
  528 + config.setJdbcUrl(jdbcUrl);
  529 + config.setUsername(jdbcUserName);
  530 + config.setPassword(jdbcPassword);
  531 + config.setDriverClassName("org.postgresql.Driver");
  532 + config.setMaximumPoolSize(5);
  533 + config.setMinimumIdle(5);
  534 + config.setConnectionTimeout(60000);
  535 + config.setConnectionTestQuery("SELECT 1");
  536 +
  537 + dataSource = new HikariDataSource(config);
  538 + log.info("Hikari连接池配置完成");
  539 +
  540 + connection = dataSource.getConnection();
  541 + log.info("数据库连接成功");
  542 +
  543 + statement = connection.prepareStatement(selectEnergySql);
  544 + log.info("执行SQL查询: {}", selectSql);
  545 +
  546 + resultSet = statement.executeQuery();
  547 + ResultSetMetaData metaData = resultSet.getMetaData();
  548 + int columnCount = metaData.getColumnCount();
  549 + log.info("查询结果集元数据获取成功,共{}列", columnCount);
  550 +
  551 + int rowCount = 0;
  552 + while (resultSet.next()) {
  553 + List<Object> result = new ArrayList<>(columnCount);
  554 + for (int index = 1; index <= columnCount; index++) {
  555 + int columnType = metaData.getColumnType(index);
  556 + Object value = getTypedValue(resultSet, index, columnType);
  557 + result.add(value);
  558 + }
  559 + resultList.add(result);
  560 + rowCount++;
  561 +
  562 + // 每处理1000行记录一次日志
  563 + if (rowCount % 1000 == 0) {
  564 + log.info("已处理{}行数据", rowCount);
  565 + }
  566 + }
  567 +
  568 + log.info("数据查询完成,共获取{}行数据", rowCount);
  569 +
  570 + } catch (SQLException e) {
  571 + log.error("数据库操作异常,URL: {}, 用户名: {}", jdbcUrl, jdbcUserName, e);
  572 + } catch (Exception e) {
  573 + log.error("初始化数据库连接或查询数据时发生异常", e);
  574 + } finally {
  575 + // 释放资源
  576 + try {
  577 + if (resultSet != null) resultSet.close();
  578 + if (statement != null) statement.close();
  579 + if (connection != null) connection.close();
  580 + log.info("数据库连接资源已释放");
  581 + } catch (SQLException e) {
  582 + log.error("关闭数据库资源时发生异常", e);
  583 + }
  584 +
  585 + if (dataSource != null) {
  586 + try {
  587 + dataSource.close();
  588 + log.info("HikariDataSource连接池已关闭");
  589 + } catch (Exception e) {
  590 + log.error("关闭HikariDataSource连接池时发生异常", e);
  591 + }
  592 + }
  593 + }
  594 +
  595 + log.info("数据库操作完成,返回{}条记录", resultList.size());
  596 + return resultList;
  597 + }
  598 +
378 private Object getTypedValue(ResultSet rs, int index, int sqlType) throws SQLException { 599 private Object getTypedValue(ResultSet rs, int index, int sqlType) throws SQLException {
379 Object value; 600 Object value;
380 601
@@ -32,4 +32,19 @@ public class PanJiZoneScheduler extends AbstractZoneScheduler { @@ -32,4 +32,19 @@ public class PanJiZoneScheduler extends AbstractZoneScheduler {
32 logEnd(taskName); 32 logEnd(taskName);
33 } 33 }
34 } 34 }
  35 +
  36 + @Scheduled(cron = "${scheduler.pj.energyPush:0 0 0 * * ?}")
  37 + public void pushPjEnergyDevicesToThirdParty() {
  38 + String taskName = "PJ Devices (IoT -> 3rd Party)";
  39 + logStart(taskName);
  40 + try {
  41 + log.info("[{}] PJ pushing devices...", getZoneName());
  42 + pjDeviceReportService.batchReportEnergyEnterprise();
  43 + Thread.sleep(1000);
  44 + } catch (Exception e) {
  45 + logError(taskName, e);
  46 + } finally {
  47 + logEnd(taskName);
  48 + }
  49 + }
35 } 50 }
@@ -37,6 +37,7 @@ scheduler: @@ -37,6 +37,7 @@ scheduler:
37 push: "0 0 0/1 * * ?" 37 push: "0 0 0/1 * * ?"
38 pj: 38 pj:
39 push: "0 0/10 * * * ?" 39 push: "0 0/10 * * * ?"
  40 + energyPush: "0 0 0 * * ?"
40 jmdq: 41 jmdq:
41 pull: "0 0/10 * * * ?" 42 pull: "0 0/10 * * * ?"
42 push: "0 0/10 * * * ?" 43 push: "0 0/10 * * * ?"
@@ -154,6 +155,26 @@ pj: @@ -154,6 +155,26 @@ pj:
154 WHERE 155 WHERE
155 de.tenant_id = '0414df80-f01d-11f0-9cb8-e3376d1e7978' 156 de.tenant_id = '0414df80-f01d-11f0-9cb8-e3376d1e7978'
156 AND de.device_profile_id = '0418b010-f01d-11f0-9cb8-e3376d1e7978';" 157 AND de.device_profile_id = '0418b010-f01d-11f0-9cb8-e3376d1e7978';"
  158 + energyFormId: "t69393ccde4332f00072a08e8"
  159 + energyUniqueKeys: "entName,deviceCode,timeSpan,collectTime,energyType"
  160 + selectEnergySql: "SELECT
  161 + tko.name AS entName,
  162 + de.name AS deviceName,
  163 + dc.credentials_id AS deviceCode,
  164 + case tkl.key
  165 + when 544 then '电'
  166 + when 545 then '水'
  167 + when 546 then '天然气' end AS energyType,
  168 + COALESCE (tkl.dbl_v, tkl.long_v, 0) AS deviceValue
  169 + FROM
  170 + device de
  171 + LEFT JOIN tk_organization tko ON de.organization_id = tko.id
  172 + LEFT JOIN ts_kv_latest tkl ON de.id = tkl.entity_id
  173 + AND tkl.KEY IN (544, 545, 546)
  174 + LEFT JOIN device_credentials dc ON de.id = dc.device_id
  175 + WHERE
  176 + de.tenant_id = '0414df80-f01d-11f0-9cb8-e3376d1e7978'
  177 + AND de.device_profile_id IN ('b1845b90-6634-11f1-9cb8-e3376d1e7978', '8c195900-6634-11f1-9cb8-e3376d1e7978', '5eb07070-6634-11f1-9cb8-e3376d1e7978');"
157 178
158 wuwei: 179 wuwei:
159 third: 180 third: