package org.springblade.mdm.machinefile.service;
|
|
import com.alibaba.excel.util.StringUtils;
|
import lombok.extern.slf4j.Slf4j;
|
import org.apache.commons.codec.digest.DigestUtils;
|
import org.springblade.core.log.exception.ServiceException;
|
import org.springblade.mdm.basesetting.machine.service.MachineService;
|
import org.springblade.mdm.basesetting.machine.entity.Machine;
|
import org.springblade.mdm.commons.service.ParamService;
|
import org.springblade.mdm.gkw.programnode.vo.ProgramNameVO;
|
import org.springblade.mdm.machinefile.entity.MachineFile;
|
import org.springblade.mdm.program.service.ProgramAnnotationService;
|
import org.springblade.mdm.program.service.programannotation.*;
|
import org.springblade.mdm.utils.FileContentUtil;
|
import org.springblade.mdm.utils.ProgramFileNameParser;
|
import org.springblade.system.pojo.entity.DictBiz;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.stereotype.Component;
|
|
import java.io.BufferedInputStream;
|
import java.io.IOException;
|
import java.io.InputStream;
|
import java.nio.file.Files;
|
import java.nio.file.Path;
|
import java.nio.file.Paths;
|
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.FileTime;
|
import java.util.Date;
|
import java.util.List;
|
|
@Slf4j
|
@Component
|
public class MachineFileScanService {
|
@Autowired
|
private MachineFileService machineFileService;
|
@Autowired
|
private MachineService machineService;
|
@Autowired
|
private ProgramAnnotationService programAnnotationService;
|
@Autowired
|
private MachineAnnotationConfig annoConfig;
|
@Autowired
|
private AnnotationProcessorHelper annotationProcessorHelper;
|
/**
|
* 扫描所有机床的配置目录
|
*/
|
@Async
|
public void scanMachineFile() {
|
List<Machine> machines = machineService.getEnableMachines();
|
for (Machine machine : machines) {
|
|
//扫描新文件
|
try {
|
scanDir(machine,MachineFile.DIR_TYPE_REC);
|
}catch(Exception e) {
|
log.error("REC扫描文件异常,机床{}", machine.getCode(), e);
|
}
|
try {
|
scanDir(machine,MachineFile.DIR_TYPE_SEND);
|
}catch(Exception e) {
|
log.error("SEND扫描文件异常,机床{}", machine.getCode(), e);
|
}
|
try {
|
scanDir(machine,MachineFile.DIR_TYPE_TEMP);
|
}catch(Exception e) {
|
log.error("TEMP扫描文件异常,机床{}", machine.getCode(), e);
|
}
|
|
//清理数据库,删除文件不存在的数据
|
try {
|
clearDeletedRecords(machine,MachineFile.DIR_TYPE_REC);
|
}catch(Exception e) {
|
log.error("REC扫描文件异常,机床{}", machine.getCode(), e);
|
}
|
try {
|
clearDeletedRecords(machine,MachineFile.DIR_TYPE_SEND);
|
}catch(Exception e) {
|
log.error("SEND扫描文件异常,机床{}", machine.getCode(), e);
|
}
|
try {
|
clearDeletedRecords(machine,MachineFile.DIR_TYPE_TEMP);
|
}catch(Exception e) {
|
log.error("TEMP扫描文件异常,机床{}", machine.getCode(), e);
|
}
|
}
|
|
}
|
|
|
/**
|
* 扫描目录
|
* @param machine 机床信息
|
* @param dirType 目录类型
|
* @throws IOException
|
*/
|
public void scanDir(Machine machine,String dirType) throws IOException {
|
String basePath = MachineFileService.getBasePath(machine,dirType);
|
if(basePath == null) {
|
log.warn("目录类型不匹配:{}",dirType);
|
return;
|
}
|
Path dirPath = Paths.get(basePath);
|
if(!dirPath.toFile().exists()){
|
log.warn("扫描目录:{} 不存在",dirPath);
|
return;
|
}
|
// 只包含普通文件
|
List<Path> files = Files.list(dirPath)
|
.filter(Files::isRegularFile).toList();
|
|
//byte[] buffer = new byte[2048];
|
List<DictBiz> annotatiionList = programAnnotationService.getAnnotionDictList();
|
//boolean exists;//文件是否存在于数据库中
|
for (Path filePath : files) {
|
try {
|
MachineFile mf = readFileToMachineFile(filePath,machine,dirType,annotatiionList);
|
|
machineFileService.refreshFileData(mf);
|
|
} catch (IOException e) {
|
log.error("读取文件信息失败",e);
|
}
|
|
}
|
}
|
|
/**
|
* 读取磁盘上的文件信息
|
* @param filePath 文件路径
|
* @param machine 机器
|
* @param dirType 目录类型
|
* @param annotatiionList 注解配置字典 用于读取程序状态
|
* @return MachineFile 实例
|
* @throws IOException
|
*/
|
public MachineFile readFileToMachineFile(Path filePath,Machine machine,String dirType,List<DictBiz> annotatiionList) throws IOException {
|
MachineFile mf = new MachineFile();
|
|
mf.setTenantId("000000");
|
mf.setName(filePath.toFile().getName());
|
mf.setDirType(dirType);
|
mf.setMachineCode(machine.getCode());
|
|
|
BasicFileAttributes attrs = Files.readAttributes(
|
filePath,
|
BasicFileAttributes.class
|
);
|
|
FileTime creationTime = attrs.creationTime();
|
Date creationDate = new Date(creationTime.toMillis());
|
mf.setFileCreateTime(creationDate);
|
|
FileTime modifyTime = attrs.lastModifiedTime();
|
mf.setFileModifyTime(new Date(modifyTime.toMillis()));
|
mf.setFileSize(Files.size(filePath));
|
|
byte[] buffer = new byte[2048];
|
try (InputStream inputStream = Files.newInputStream(filePath)) {
|
// 使用输入流读取文件内容
|
inputStream.read(buffer);
|
mf.setMd5(DigestUtils.md5Hex(buffer));
|
} catch (IOException e) {
|
log.error("读取文件md5失败",e);
|
throw new ServiceException("读取文件md5失败"+e.getMessage());
|
}
|
try (InputStream inputStream = Files.newInputStream(filePath)) {
|
AnnotationProcessor annoProcessor = annotationProcessorHelper.getProcessor(machine.getMachineGroupCode());
|
AnnotationData annoData = annoProcessor.readAnnotationData(inputStream);
|
mf.setProgramStatus(annoData.getProgramStatus());
|
|
ProgramNameVO progVO = ProgramFileNameParser.parseProgramName(mf.getName());
|
if(StringUtils.isNotBlank(progVO.getLgPart())) {
|
mf.setDeviation(annoData.getDeviation());
|
}
|
}
|
return mf;
|
}
|
/**
|
* 读取文件中的程序状态
|
* @param filePath 文件路径
|
* @param controlSystem
|
* @param annotatiionList 注释配置字典
|
* @return 状态的整数之和
|
* @throws IOException
|
*/
|
public int readProgramStatus(Path filePath,String controlSystem,List<DictBiz> annotatiionList) throws IOException {
|
int programStatus = MachineFile.PROGRAM_STATUS_UNKNOWN;
|
try(InputStream ins = Files.newInputStream(filePath);
|
BufferedInputStream byteInsStream = new BufferedInputStream(ins)){
|
|
boolean isText= FileContentUtil.isTextFile(byteInsStream);
|
if(!isText){
|
return MachineFile.PROGRAM_STATUS_UNKNOWN;
|
}
|
byteInsStream.reset();
|
|
AnnotationProcessor annoProcessor = ProcessorHelper.getProcessor(controlSystem,annoConfig);
|
String statusLine = FileContentUtil.readLineAt(byteInsStream, annoProcessor.getAnnotationProperties().getStatusLineIndex());
|
if(AnnotationUtil.isAnnotation(statusLine,controlSystem,annotatiionList)){
|
String progStatusTxt = AnnotationUtil.removeAnnotation(controlSystem,statusLine,annotatiionList);
|
if(AnnotationUtil.SQ.equals(progStatusTxt)){
|
programStatus = MachineFile.PROGRAM_STATUS_TRY;
|
}else if(AnnotationUtil.GH.equals(progStatusTxt)){
|
programStatus = MachineFile.PROGRAM_STATUS_CURED;
|
}else if(AnnotationUtil.LG.equals(progStatusTxt)){
|
programStatus = MachineFile.PROGRAM_STATUS_DIVIASTION;
|
}
|
}
|
}
|
|
return programStatus;
|
}
|
|
/**
|
* 清理已经删除了文件的记录
|
* @param machine
|
* @param dirType
|
* @throws IOException
|
*/
|
void clearDeletedRecords(Machine machine,String dirType) throws IOException {
|
List<MachineFile> machineFiles = this.machineFileService.lambdaQuery().eq(MachineFile::getDirType,dirType)
|
.eq(MachineFile::getMachineCode,machine.getCode()).list();
|
|
String basePath = MachineFileService.getBasePath(machine,dirType);
|
if(basePath == null) {
|
log.warn("目录类型不匹配:{}",dirType);
|
return;
|
}
|
Path dirPath = Paths.get(basePath);
|
if(!dirPath.toFile().exists()){
|
log.warn("扫描目录:{} 不存在",dirPath);
|
return;
|
}
|
|
List<Path> files = Files.list(dirPath)
|
.filter(Files::isRegularFile).toList();
|
|
for(MachineFile mf : machineFiles){
|
long findCount = files.stream().filter(filePath -> filePath.toFile().getName().equals(mf.getName())).count();
|
if(findCount == 0){
|
//文件夹内没找到,需要删除记录
|
mf.markFileDeleted();
|
this.machineFileService.updateById(mf);
|
}
|
}
|
}
|
}
|