¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.jeecg.modules.quartz.job; |
| | | |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.collections.CollectionUtils; |
| | | import org.apache.commons.csv.CSVFormat; |
| | | import org.apache.commons.csv.CSVPrinter; |
| | | import org.jeecg.modules.iot.entity.Equipment; |
| | | import org.jeecg.modules.iot.entity.EquipmentCsvData; |
| | | import org.jeecg.modules.iot.service.IEquipmentService; |
| | | import org.quartz.Job; |
| | | import org.quartz.JobExecutionContext; |
| | | import org.quartz.JobExecutionException; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.jdbc.datasource.DataSourceUtils; |
| | | |
| | | import javax.sql.DataSource; |
| | | import java.io.File; |
| | | import java.io.FileWriter; |
| | | import java.io.IOException; |
| | | import java.lang.reflect.Method; |
| | | import java.sql.*; |
| | | import java.time.LocalDateTime; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.time.format.DateTimeParseException; |
| | | import java.time.temporal.ChronoUnit; |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * 宿¶çæcsvæä»¶ |
| | | * |
| | | * @Author Scott |
| | | */ |
| | | @Slf4j |
| | | public class ParameterCsvJob implements Job { |
| | | |
| | | @Autowired |
| | | private IEquipmentService equipmentService; |
| | | @Autowired |
| | | private DataSource dataSource; |
| | | // CSVæä»¶ä¿åè·¯å¾ |
| | | private static final String CSV_FILE_PATH = "D:/iot/"; |
| | | private static final Map<String, String> FIELD_MAPPING = new HashMap<>(); |
| | | |
| | | static { |
| | | // åå§ååæ®µæ å°ï¼keyæ¯æ°æ®åºå段åï¼valueæ¯CSV/å®ä½ç±»å段å |
| | | FIELD_MAPPING.put("CollectTime", "k_ts"); |
| | | FIELD_MAPPING.put("EquipmentID", "k_device"); |
| | | FIELD_MAPPING.put("ProgramNo", "ProgramNumber"); |
| | | // å¯ä»¥æ·»å å
¶ä»éè¦æ å°çåæ®µ |
| | | } |
| | | |
| | | private static final List<DateTimeFormatter> INPUT_FORMATTERS = Arrays.asList( |
| | | DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"), // æ åæ ¼å¼ï¼ç®æ æ ¼å¼ï¼ |
| | | DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"), // ææ åé |
| | | DateTimeFormatter.ofPattern("yyyy-M-d H:m:s"), // ä¸è¡¥é¶æ ¼å¼ |
| | | DateTimeFormatter.ofPattern("yyyy/MM/d HH:mm:ss"), // æ··åæ ¼å¼ |
| | | DateTimeFormatter.ISO_LOCAL_DATE_TIME // 带Tçæ ¼å¼ï¼å¦2025-09-15T10:21:11ï¼ |
| | | ); |
| | | |
| | | // è¾åºæ ¼å¼ï¼ä¸¥æ ¼æå®ä¸ºyyyy-MM-dd HH:mm:ssï¼è¡¥é¶+è¿åç¬¦ï¼ |
| | | private static final DateTimeFormatter OUTPUT_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); |
| | | |
| | | @Override |
| | | public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { |
| | | // æ¥è¯¢ææèè®¾å¤ |
| | | List<Equipment> equipmentByTypeList = equipmentService.findEquipmentByTypeList(); |
| | | if (CollectionUtils.isNotEmpty(equipmentByTypeList)) { |
| | | // éåèè®¾å¤ |
| | | equipmentByTypeList.forEach(eq -> { |
| | | String tableName = eq.getControlSystem() + "_" + eq.getEqptCode().replace('-', '_'); |
| | | if (doesTheTableExist(tableName)) { |
| | | queryLastHourDataAndExportToCsv(tableName); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | |
| | | // éªè¯æ¯å¦åå¨ |
| | | Boolean doesTheTableExist(String tableName) { |
| | | boolean tableExists = false; |
| | | // è·åæ°æ®åºè¿æ¥ |
| | | try (Connection connection = dataSource.getConnection()) { |
| | | // æ¥è¯¢èè®¾å¤æ¯å¦æå表 |
| | | // è·åæ°æ®åºäº§åå称以åºåæ°æ®åºç±»å |
| | | String databaseProductName = connection.getMetaData().getDatabaseProductName(); |
| | | // 表åè½¬æ¢ |
| | | if (databaseProductName.contains("MySQL")) { |
| | | // MySQL: æ¥è¯¢information_schemaåº |
| | | String sql = "SELECT COUNT(*) FROM information_schema.tables " + |
| | | "WHERE table_schema = DATABASE() AND table_name = ?"; |
| | | try (PreparedStatement stmt = connection.prepareStatement(sql)) { |
| | | stmt.setString(1, tableName); |
| | | try (ResultSet rs = stmt.executeQuery()) { |
| | | if (rs.next()) { |
| | | tableExists = rs.getInt(1) > 0; |
| | | } |
| | | } |
| | | } |
| | | } else if (databaseProductName.contains("SQL Server")) { |
| | | // SQL Server: æ¥è¯¢sys.tables |
| | | String sql = "SELECT COUNT(*) FROM sys.tables WHERE name = ?"; |
| | | try (PreparedStatement stmt = connection.prepareStatement(sql)) { |
| | | stmt.setString(1, tableName); |
| | | try (ResultSet rs = stmt.executeQuery()) { |
| | | if (rs.next()) { |
| | | tableExists = rs.getInt(1) > 0; |
| | | } |
| | | } |
| | | } |
| | | } else { |
| | | log.info("䏿¯æçæ°æ®åºç±»å: " + databaseProductName); |
| | | } |
| | | } catch (SQLException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return tableExists; |
| | | } |
| | | |
| | | public void queryLastHourDataAndExportToCsv(String tableName) { |
| | | LocalDateTime now = LocalDateTime.now(); |
| | | LocalDateTime lastHourStart = now.truncatedTo(ChronoUnit.HOURS).minusHours(1); |
| | | LocalDateTime lastHourEnd = lastHourStart.plusHours(1).minusSeconds(1); |
| | | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); |
| | | String startTimeStr = lastHourStart.format(formatter); |
| | | String endTimeStr = lastHourEnd.format(formatter); |
| | | log.info("æ¥è¯¢æ¶é´èå´ï¼{} ~ {}", startTimeStr, endTimeStr); |
| | | |
| | | String sql = String.format("SELECT * FROM %s WHERE CollectTime BETWEEN ? AND ?", tableName); |
| | | List<EquipmentCsvData> dataList = new ArrayList<>(); |
| | | |
| | | try (Connection conn = DataSourceUtils.getConnection(dataSource); |
| | | PreparedStatement pstmt = conn.prepareStatement(sql)) { |
| | | pstmt.setString(1, startTimeStr); |
| | | pstmt.setString(2, endTimeStr); |
| | | |
| | | try (ResultSet rs = pstmt.executeQuery()) { |
| | | ResultSetMetaData metaData = rs.getMetaData(); |
| | | int columnCount = metaData.getColumnCount(); |
| | | log.debug("æ°æ®åºè¿ååæ®µæ»æ°ï¼{}ï¼å段å表ï¼{}", columnCount, getColumnNames(metaData)); |
| | | |
| | | // éªè¯å
³é®å段æ¯å¦åå¨ |
| | | boolean hasCollectTime = false; |
| | | boolean hasEquipmentID = false; |
| | | for (int i = 1; i <= columnCount; i++) { |
| | | String colName = metaData.getColumnName(i); |
| | | if ("CollectTime".equals(colName)) hasCollectTime = true; |
| | | if ("EquipmentID".equals(colName)) hasEquipmentID = true; |
| | | } |
| | | log.info("æ°æ®åºæ¯å¦å
å«CollectTimeï¼{}ï¼æ¯å¦å
å«EquipmentIDï¼{}", hasCollectTime, hasEquipmentID); |
| | | |
| | | int totalCount = 0; |
| | | while (rs.next()) { |
| | | totalCount++; |
| | | EquipmentCsvData csvData = new EquipmentCsvData(); |
| | | |
| | | // æå¨å¤çå
³é®å段ï¼ç¡®ä¿æ å°çæï¼ |
| | | handleCriticalFields(csvData, rs); |
| | | |
| | | // å¤çå
¶ä»å段 |
| | | for (int i = 1; i <= columnCount; i++) { |
| | | String dbColName = metaData.getColumnName(i); |
| | | // è·³è¿å·²æå¨å¤ççåæ®µ |
| | | if ("CollectTime".equals(dbColName) || "EquipmentID".equals(dbColName)) { |
| | | continue; |
| | | } |
| | | Object value = rs.getObject(i); |
| | | setFieldValue(csvData, dbColName, value); |
| | | } |
| | | |
| | | dataList.add(csvData); |
| | | log.debug("第{}æ¡æ°æ®ï¼k_device={}, k_ts={}", |
| | | totalCount, csvData.getK_device(), csvData.getK_ts()); |
| | | } |
| | | log.info("æ¥è¯¢å®æï¼å
±{}æ¡æ°æ®", totalCount); |
| | | } |
| | | } catch (SQLException e) { |
| | | log.error("æ¥è¯¢å¤±è´¥", e); |
| | | return; |
| | | } |
| | | |
| | | if (!dataList.isEmpty()) { |
| | | String fileName = CSV_FILE_PATH + tableName + "_" + |
| | | lastHourStart.format(DateTimeFormatter.ofPattern("yyyyMMddHH")) + ".csv"; |
| | | exportToCsv(dataList, fileName); |
| | | } else { |
| | | log.info("æ æ°æ®å¯¼åº"); |
| | | } |
| | | } |
| | | |
| | | // æå¨å¤çå
³é®å段ï¼é¿å
åå°å¤±è´¥ï¼ |
| | | private void handleCriticalFields(EquipmentCsvData csvData, ResultSet rs) throws SQLException { |
| | | // æºç»ç¶æ |
| | | Object status = rs.getObject("Oporation"); |
| | | if (status != null) { |
| | | String statusStr = status.toString().trim(); |
| | | // ç¶æå¼è½¬æ¢æ å° |
| | | switch (statusStr) { |
| | | case "0": |
| | | csvData.setStatus("3"); |
| | | break; |
| | | case "2": |
| | | csvData.setStatus("6"); |
| | | break; |
| | | case "3": |
| | | csvData.setStatus("10"); |
| | | break; |
| | | } |
| | | // æºç»ç¶æ |
| | | Object isAlarm = rs.getObject("lsAlarm"); |
| | | if (isAlarm != null && status.toString().trim().equals("True")) { |
| | | csvData.setStatus("16"); |
| | | } |
| | | } |
| | | // 设å¤ç¶æ |
| | | Object oporation = rs.getObject("Oporation"); |
| | | if (oporation != null) { |
| | | csvData.setThreeColorIndicatorState(oporation.toString().trim()); |
| | | } |
| | | // å¤çEquipmentIDâk_deviceï¼ä¿æä¸åï¼ |
| | | Object equipmentId = rs.getObject("EquipmentID"); |
| | | if (equipmentId != null) { |
| | | csvData.setK_device(equipmentId.toString().trim()); |
| | | } |
| | | // ç¨åºç¼å· |
| | | Object programNumber = rs.getObject("ProgramNumber"); |
| | | if (programNumber != null) { |
| | | csvData.setProgramNo(programNumber.toString().trim()); |
| | | } |
| | | // è¿ç»åç |
| | | Object feedOverride = rs.getObject("FeedOverride"); |
| | | if (feedOverride != null) { |
| | | csvData.setFeedrateOverride(feedOverride.toString().trim()); |
| | | } |
| | | // æ¥è¦ä»£ç |
| | | Object alarmNo = rs.getObject("AlarmNo"); |
| | | if (alarmNo != null) { |
| | | csvData.setAlarmCode(alarmNo.toString().trim()); |
| | | } |
| | | // æ¥è¦å
容 |
| | | Object alarmInfo = rs.getObject("AlarmInfo"); |
| | | if (alarmInfo != null) { |
| | | csvData.setAlarmMessage(alarmInfo.toString().trim()); |
| | | } |
| | | // 主轴转é |
| | | Object actualSpindleSpeed = rs.getObject("ActualSpindleSpeed"); |
| | | if (actualSpindleSpeed != null) { |
| | | csvData.setSpindleSpeed(actualSpindleSpeed.toString().trim()); |
| | | } |
| | | // è¿ç»é度 |
| | | Object actualFeedRate = rs.getObject("ActualFeedRate"); |
| | | if (actualSpindleSpeed != null) { |
| | | csvData.setFeedRate(actualFeedRate.toString().trim()); |
| | | } |
| | | // å½åæ§è¡è¡å· |
| | | Object executingCode = rs.getObject("ExecutingCode"); |
| | | if (executingCode != null) { |
| | | csvData.setCurrentExecutionLine(executingCode.toString().trim()); |
| | | } |
| | | // æºæ¢°åæ |
| | | Object xmachine = rs.getObject("Xmachine"); |
| | | if (xmachine != null) { |
| | | csvData.setXmechanicalCoordinate(xmachine.toString().trim()); |
| | | } |
| | | // æºæ¢°åæ |
| | | Object ymachine = rs.getObject("Ymachine"); |
| | | if (ymachine != null) { |
| | | csvData.setYmechanicalCoordinate(ymachine.toString().trim()); |
| | | } |
| | | // æºæ¢°åæ |
| | | Object zmachine = rs.getObject("Zmachine"); |
| | | if (zmachine != null) { |
| | | csvData.setZmechanicalCoordinate(zmachine.toString().trim()); |
| | | } |
| | | // æºæ¢°åæ |
| | | Object amachine = rs.getObject("Amachine"); |
| | | if (amachine != null) { |
| | | csvData.setAmechanicalCoordinateA(amachine.toString().trim()); |
| | | } |
| | | // æºæ¢°åæ |
| | | Object bmachine = rs.getObject("Bmachine"); |
| | | if (bmachine != null) { |
| | | csvData.setBmechanicalCoordinateB(bmachine.toString().trim()); |
| | | } |
| | | // ç»å¯¹åæ |
| | | Object aabsolute = rs.getObject("Aabsolute"); |
| | | if (aabsolute != null) { |
| | | csvData.setAabsoluteCoordinate(aabsolute.toString().trim()); |
| | | } |
| | | // ç»å¯¹åæ |
| | | Object babsolute = rs.getObject("Babsolute"); |
| | | if (babsolute != null) { |
| | | csvData.setBabsoluteCoordinate(babsolute.toString().trim()); |
| | | } |
| | | // ç»å¯¹åæ |
| | | Object xabsolute = rs.getObject("Xabsolute"); |
| | | if (xabsolute != null) { |
| | | csvData.setXabsoluteCoordinate(xabsolute.toString().trim()); |
| | | } |
| | | // ç»å¯¹åæ |
| | | Object yabsolute = rs.getObject("Yabsolute"); |
| | | if (babsolute != null) { |
| | | csvData.setYabsoluteCoordinate(yabsolute.toString().trim()); |
| | | } |
| | | // ç»å¯¹åæ |
| | | Object zabsolute = rs.getObject("Zabsolute"); |
| | | if (zabsolute != null) { |
| | | csvData.setZabsoluteCoordinate(zabsolute.toString().trim()); |
| | | } |
| | | // ç¸å¯¹åæ |
| | | Object arelative = rs.getObject("Arelative"); |
| | | if (zabsolute != null) { |
| | | csvData.setZabsoluteCoordinate(arelative.toString().trim()); |
| | | } |
| | | // å¤çCollectTimeâk_tsï¼ä½¿ç¨æ¹è¿çè½¬æ¢æ¹æ³ï¼ |
| | | Object collectTimeObj = rs.getObject("CollectTime"); |
| | | if (collectTimeObj != null) { |
| | | String formattedTime = convertTimeFormat(collectTimeObj.toString()); |
| | | csvData.setK_ts(formattedTime); |
| | | } |
| | | } |
| | | |
| | | // å¤çå
¶ä»å段çéç¨æ¹æ³ |
| | | private void setFieldValue(EquipmentCsvData csvData, String dbColName, Object value) { |
| | | if (value == null) return; |
| | | |
| | | String fieldName = FIELD_MAPPING.getOrDefault(dbColName, dbColName); |
| | | fieldName = fieldName.replaceAll("[^a-zA-Z0-9]", ""); |
| | | |
| | | try { |
| | | String setterName = "set" + |
| | | fieldName.substring(0, 1).toUpperCase() + |
| | | fieldName.substring(1); |
| | | Method setter = EquipmentCsvData.class.getMethod(setterName, String.class); |
| | | setter.invoke(csvData, value.toString()); |
| | | } catch (Exception e) { |
| | | log.debug("åæ®µ{}设置失败ï¼å¯å¿½ç¥ï¼", fieldName); |
| | | } |
| | | } |
| | | |
| | | private void exportToCsv(List<EquipmentCsvData> dataList, String filePath) { |
| | | File file = new File(filePath); |
| | | File parent = file.getParentFile(); |
| | | if (parent != null && !parent.exists()) { |
| | | parent.mkdirs(); |
| | | } |
| | | |
| | | try (FileWriter writer = new FileWriter(file); |
| | | CSVPrinter csvPrinter = new CSVPrinter(writer, CSVFormat.DEFAULT |
| | | .withHeader("k_device", "k_ts", "IsConnected", "Status", |
| | | "ThreeColorIndicatorState", "ProgramName", "ProgramNo", |
| | | "SubProgramNo", "SpindleOverride", "FeedrateOverride", |
| | | "AlarmCode", "AlarmMessage", "SpindleLoad", "SpindleSpeed", |
| | | "FeedRate", "CurrentExecutionLine", "ExecutingCode", |
| | | "ToolNo", "XmechanicalCoordinate", "YmechanicalCoordinate", |
| | | "ZmechanicalCoordinate", "AmechanicalCoordinateA", |
| | | "BmechanicalCoordinateB", "XabsoluteCoordinate", |
| | | "YabsoluteCoordinate", "ZabsoluteCoordinate", |
| | | "AabsoluteCoordinate", "BabsoluteCoordinate", "VTVersion", |
| | | "SerialNumber", "Temperature", "XaccelerationRMS", |
| | | "YaccelerationRMS", "ZaccelerationRMS", "XvelocityRMS", |
| | | "YvelocityRMS", "ZvelocityRMS", "XdisplacementRMS", |
| | | "YdisplacementRMS", "ZdisplacementRMS", "XvelocityMax", |
| | | "YvelocityMax", "ZvelocityMax", "XaccelerationMax", |
| | | "YaccelerationMax", "ZaccelerationMax", "XdisplacementMax", |
| | | "YdisplacementMax", "ZdisplacementMax", "AccelerationHrate", |
| | | "AccelerationLrate", "VelocityHrate", "VelocityLrate", |
| | | "DisplacementHrate", "DisplacementLrate"))) { |
| | | |
| | | for (EquipmentCsvData data : dataList) { |
| | | csvPrinter.printRecord( |
| | | data.getK_device(), |
| | | data.getK_ts(), |
| | | data.getIsConnected(), |
| | | data.getStatus(), |
| | | data.getThreeColorIndicatorState(), |
| | | data.getProgramName(), |
| | | data.getProgramNo(), |
| | | data.getSubProgramNo(), |
| | | data.getSpindleOverride(), |
| | | data.getFeedrateOverride(), |
| | | data.getAlarmCode(), |
| | | data.getAlarmMessage(), |
| | | data.getSpindleLoad(), |
| | | data.getSpindleSpeed(), |
| | | data.getFeedRate(), |
| | | data.getCurrentExecutionLine(), |
| | | data.getExecutingCode(), |
| | | data.getToolNo(), |
| | | data.getXmechanicalCoordinate(), |
| | | data.getYmechanicalCoordinate(), |
| | | data.getZmechanicalCoordinate(), |
| | | data.getAmechanicalCoordinateA(), |
| | | data.getBmechanicalCoordinateB(), |
| | | data.getXabsoluteCoordinate(), |
| | | data.getYabsoluteCoordinate(), |
| | | data.getZabsoluteCoordinate(), |
| | | data.getAabsoluteCoordinate(), |
| | | data.getBabsoluteCoordinate(), |
| | | data.getVTVersion(), |
| | | data.getSerialNumber(), |
| | | data.getTemperature(), |
| | | data.getXaccelerationRMS(), |
| | | data.getYaccelerationRMS(), |
| | | data.getZaccelerationRMS(), |
| | | data.getXvelocityRMS(), |
| | | data.getYvelocityRMS(), |
| | | data.getZvelocityRMS(), |
| | | data.getXdisplacementRMS(), |
| | | data.getYdisplacementRMS(), |
| | | data.getZdisplacementRMS(), |
| | | data.getXvelocityMax(), |
| | | data.getYvelocityMax(), |
| | | data.getZvelocityMax(), |
| | | data.getXaccelerationMax(), |
| | | data.getYaccelerationMax(), |
| | | data.getZaccelerationMax(), |
| | | data.getXdisplacementMax(), |
| | | data.getYdisplacementMax(), |
| | | data.getZdisplacementMax(), |
| | | data.getAccelerationHrate(), |
| | | data.getAccelerationLrate(), |
| | | data.getVelocityHrate(), |
| | | data.getVelocityLrate(), |
| | | data.getDisplacementHrate(), |
| | | data.getDisplacementLrate() |
| | | ); |
| | | } |
| | | log.info("CSVå¯¼åºæåï¼{}", filePath); |
| | | } catch (IOException e) { |
| | | log.error("CSV导åºå¤±è´¥", e); |
| | | } |
| | | } |
| | | |
| | | private String getColumnNames(ResultSetMetaData metaData) throws SQLException { |
| | | StringBuilder sb = new StringBuilder(); |
| | | for (int i = 1; i <= metaData.getColumnCount(); i++) { |
| | | sb.append(metaData.getColumnName(i)).append(","); |
| | | } |
| | | return sb.toString(); |
| | | } |
| | | |
| | | // æ¶é´æ ¼å¼è½¬æ¢æ ¸å¿æ¹æ³ |
| | | private String convertTimeFormat(String originalTime) { |
| | | if (originalTime == null || originalTime.trim().isEmpty()) { |
| | | log.warn("åå§æ¶é´ä¸ºç©º"); |
| | | return ""; |
| | | } |
| | | |
| | | // å»é¤åå§æ¶é´ä¸çå¤ä½ç©ºæ ¼ |
| | | String trimmedTime = originalTime.trim().replaceAll("\\s+", " "); |
| | | |
| | | // å°è¯ææå¯è½çè¾å
¥æ ¼å¼è¿è¡è§£æ |
| | | for (DateTimeFormatter formatter : INPUT_FORMATTERS) { |
| | | try { |
| | | LocalDateTime dateTime = LocalDateTime.parse(trimmedTime, formatter); |
| | | // 强å¶è½¬æ¢ä¸ºç®æ æ ¼å¼ |
| | | String formattedTime = dateTime.format(OUTPUT_FORMATTER); |
| | | log.debug("æ¶é´è½¬æ¢æåï¼{} â {}", trimmedTime, formattedTime); |
| | | return formattedTime; |
| | | } catch (DateTimeParseException e) { |
| | | // å°è¯ä¸ä¸ç§æ ¼å¼ |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | // æææ ¼å¼é½è§£æå¤±è´¥æ¶ï¼è®°å½è¦åå¹¶è¿ååå§å¼ï¼é¿å
ç ´åæ°æ®ï¼ |
| | | log.warn("æ æ³è½¬æ¢æ¶é´æ ¼å¼ä¸ºyyyy-MM-dd HH:mm:ssï¼åå§å¼ï¼{}", trimmedTime); |
| | | return trimmedTime; |
| | | } |
| | | |
| | | } |