package art.servers.gost.access.controller; import art.library.interop.serialization.Serialization; import art.library.model.devices.DeviceStatus; import art.library.model.devices.gost.access.AccessEnforcement; import art.library.model.devices.gost.access.types.AccessEnforcement_Detection; import art.library.model.devices.gost.access.types.AccessEnforcement_Detection_Image; import art.library.model.devices.gost.access.types.AccessEnforcement_Detection_State; import art.library.model.devices.gost.access.types.AccessEnforcement_Detection_State_Vehicle; import art.library.model.devices.gost.access.types.AccessEnforcement_Detection_VPV; import art.servers.gost.access.Shared; import art.servers.gost.access.types.DatabasePoolConnection; import com.xuggle.mediatool.IMediaWriter; import com.xuggle.mediatool.ToolFactory; import com.xuggle.xuggler.ICodec; import com.xuggle.xuggler.IRational; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.stream.Stream; import javax.imageio.ImageIO; public class Controller_ACCESS_VPV extends Controller_ACCESS { private static final int VIDEO_FRAME_RATE = 1; private static final String REG_DIR = "/REG"; private static final String LOG_DIR = "/LOG"; private static final String AMB_DIR = "/FOTO/AMB"; private static final String AMB2_DIR = "/FOTO/AMB2"; private static final String LPR_DIR = "/FOTO/LPR"; public Controller_ACCESS_VPV(AccessEnforcement access, DatabasePoolConnection database) { super(access, database); this.setName(Shared.getMessage("Controller VPV") + " " + access.information.name); } public AccessEnforcement getAccessEnforcement() { return (AccessEnforcement)getDevice(); } public void run() { Shared.traceInformation(getName(), Shared.getMessage("Starting")); initialise(); while ((isInterrupted() == false) && (exit == false)) { try { if (Shared.isServerEnabled() == true) { update(); } } catch (Exception exception) { exception.printStackTrace(); } try { sleep(1000); } catch (Exception e) { } if (Shared.model.existsDevice(this.getAccessEnforcement().getIdentifier()) == false) { Shared.traceInformation(getName(), Shared.getMessage("Device no longer exists")); exit = true; } } Shared.traceInformation(getName(), Shared.getMessage("Finishing")); } private void online(AccessEnforcement clon) throws Exception { clon.setAlarm("alarm_offline", false); clon.setAlarm("alarm_invalid", false); clon.getDeviceStatus().status = DeviceStatus.STATUS_ONLINE; Shared.model.updateDevice(getAccessEnforcement(), clon); } private void update() throws Exception { AccessEnforcement clon = Serialization.clone(getAccessEnforcement()); online(clon); File detectionsPath = new File(clon.getDeviceInformation().vpv.path); if(detectionsPath.listFiles() == null) return; for(File detectionDateDir : detectionsPath.listFiles()) { File regFileDir = new File(detectionDateDir.getPath() + REG_DIR); File ambFileDir = new File(detectionDateDir.getPath() + AMB_DIR); File amb2FileDir = new File(detectionDateDir.getPath() + AMB2_DIR); File lprFileDir = new File(detectionDateDir.getPath() + LPR_DIR); if(regFileDir.listFiles() == null) continue; for (File regFile : regFileDir.listFiles()) { if(regFile.exists() == false) continue; String[] regCSV = Files.readAllLines(regFile.toPath()) .get(0) .split(","); AccessEnforcement_Detection detection = getDetection(regCSV, lprFileDir, ambFileDir, amb2FileDir); updateDatabaseDetection(getAccessEnforcement().getDeviceInformation(), detection); moveFiles(detectionDateDir, regCSV[0]); } } } public AccessEnforcement_Detection getDetection(String[] regCSV, File lprFileDir, File ambFileDir, File amb2FileDir) throws IOException { String number = regCSV[0]; String plate = regCSV[1]; String exitDate = regCSV[2]; String exitTime = regCSV[3]; String entryDate = regCSV[5]; String entryTime = regCSV[6]; String exitImagePath = lprFileDir.getPath() + "/" + number + "/" + regCSV[4]; String entryImagePath = lprFileDir.getPath() + "/" + number + "/" + regCSV[7]; File[] imageFilesAMB = new File(ambFileDir.getPath() + "/" + number).listFiles(); File[] imageFilesAMB2 = new File(amb2FileDir.getPath() + "/" + number).listFiles(); AccessEnforcement_Detection detection = new AccessEnforcement_Detection(); { detection.device = getAccessEnforcement().getDeviceInformation(); detection.timestamp = getEpochDatetime(entryDate, entryTime); AccessEnforcement_Detection_State detectionState = new AccessEnforcement_Detection_State(); { detectionState.timestamp = getEpochDatetime(entryDate, entryTime); detectionState.vehicle = new AccessEnforcement_Detection_State_Vehicle(); { detectionState.vehicle.plate = plate.toUpperCase(); detectionState.vehicle.confidence = 100f; } } detection.states.add(detectionState); detection.vpv = new AccessEnforcement_Detection_VPV(); { detection.vpv.entryIdentifier = getAccessEnforcement().getDeviceInformation().vpv.vpvs[0]; detection.vpv.exitIdentifier = getAccessEnforcement().getDeviceInformation().vpv.vpvs[1]; detection.vpv.entryLocation = getAccessEnforcement().getDeviceInformation().location; detection.vpv.exitLocation = getAccessEnforcement().getDeviceInformation().location; detection.vpv.entryTimestamp = getEpochDatetime(entryDate, entryTime); detection.vpv.exitTimestamp = getEpochDatetime(exitDate, exitTime); } AccessEnforcement_Detection_Image imageEntryLPR = new AccessEnforcement_Detection_Image(); { imageEntryLPR.format = AccessEnforcement_Detection_Image.FORMAT_JPG; imageEntryLPR.data = Files.readAllBytes(new File(entryImagePath).toPath()); imageEntryLPR.name = Shared.getMessage("Plate entry"); } AccessEnforcement_Detection_Image imageExitLPR = new AccessEnforcement_Detection_Image(); { imageExitLPR.format = AccessEnforcement_Detection_Image.FORMAT_JPG; imageExitLPR.data = Files.readAllBytes(new File(exitImagePath).toPath()); imageExitLPR.name = Shared.getMessage("Plate exit"); } AccessEnforcement_Detection_Image videoAMB = new AccessEnforcement_Detection_Image(); { videoAMB.format = AccessEnforcement_Detection_Image.FORMAT_AVI; videoAMB.data = encodeVideoFile(imageFilesAMB); videoAMB.name = Shared.getMessage("Video entry"); } AccessEnforcement_Detection_Image videoAMB2 = new AccessEnforcement_Detection_Image(); { videoAMB2.format = AccessEnforcement_Detection_Image.FORMAT_AVI; videoAMB2.data = encodeVideoFile(imageFilesAMB2); videoAMB2.name = Shared.getMessage("Video exit"); } detection.images.add(imageEntryLPR); detection.images.add(imageExitLPR); detection.images.add(videoAMB); detection.images.add(videoAMB2); } return detection; } private byte[] encodeVideoFile(File[] imageFiles) throws IOException { String outputFile = imageFiles[0].getParent() + "/temp.avi"; IMediaWriter writer = ToolFactory.makeWriter(outputFile); IRational rationalFrameRate = IRational.make(VIDEO_FRAME_RATE, 1); writer.addVideoStream(0, 0, ICodec.ID.CODEC_ID_H264, rationalFrameRate, 1280, 720); int index = 0; for (File imgFile : Stream.of(imageFiles).filter(file -> file.getPath().endsWith(".jpg")).toArray(File[]::new)) { BufferedImage image; try { image = ImageIO.read(imgFile); } catch (IOException e) { break; } long timeStamp = index * (1000 / VIDEO_FRAME_RATE); writer.encodeVideo(0, image, timeStamp, java.util.concurrent.TimeUnit.MILLISECONDS); index++; } writer.close(); byte[] data = Files.readAllBytes(new File(outputFile).toPath()); Files.delete(new File(outputFile).toPath()); return data; } private static long getEpochDatetime(String date, String time) { LocalDateTime localDateTime = LocalDateTime.parse(date + " " + time, DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss.[SSS][SS][S]")); return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); } private String getProcessedDetectionsPath(String sourcePath) { return sourcePath.replace("\\", "/") .replace(getAccessEnforcement().getDeviceInformation().vpv.path, getAccessEnforcement().getDeviceInformation().storage.processedFolder); } private void moveToProcessed(File file) { try { File destinationFile = new File(getProcessedDetectionsPath(file.getPath())); if (Files.exists(destinationFile.getParentFile().toPath()) == false) { Files.createDirectories(destinationFile.getParentFile().toPath()); } Files.move(file.toPath(), destinationFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } catch (Exception ex){} } private void moveFiles(File detectionDate, String csv) throws IOException { String parentDir = detectionDate.getPath(); String detectionNumber = csv.split(",")[0]; File regFile = new File(parentDir + REG_DIR + "/" + detectionNumber + ".txt"); File logFile = new File(parentDir + LOG_DIR + "/log" + detectionNumber + ".log"); File ambDir = new File(parentDir + AMB_DIR + "/" + detectionNumber); File amb2Dir = new File(parentDir + AMB2_DIR + "/" + detectionNumber); File lprDir = new File(parentDir + LPR_DIR + "/" + detectionNumber); moveToProcessed(regFile); moveToProcessed(logFile); Stream.of(ambDir.listFiles()) .forEach(this::moveToProcessed); Stream.of(amb2Dir.listFiles()) .forEach(this::moveToProcessed); Stream.of(lprDir.listFiles()) .forEach(this::moveToProcessed); } }