package art.servers.gost.access.controller; import art.library.interop.serialization.Serialization; import art.library.interop.web.HttpsRequest; import art.library.model.devices.gost.access.AccessEnforcement; import art.library.model.devices.gost.access.AccessEnforcementInformation; import art.library.model.devices.gost.access.information.AccessEnforcementInformation_Neural_Lane; 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_Discarded; import art.library.model.devices.gost.access.types.AccessEnforcement_Detection_State_Vehicle; import art.library.model.devices.lpr.erm.types.ErmDetection; import art.servers.controller.Controller; import art.servers.gost.access.Shared; import art.servers.gost.access.configuration.Configuration; import art.servers.gost.access.configuration.ConfigurationDetail; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; public class Controller_ACCESS_Neural_Detections_Kielce extends Controller { private Controller_ACCESS_Neural_Kielce controller = null; private ConfigurationDetail detail = null; // Last timestamp detection private long lastDetection = -1; // Statistics timer private ScheduledFuture scheduledFuture = null; private int counterDetections = 0; public Controller_ACCESS_Neural_Detections_Kielce(Controller_ACCESS_Neural_Kielce controller) { this.controller = controller; this.setName(Shared.getMessage("Controller detections") + " " + controller.getAccessEnforcement().information.name); this.detail = ((Configuration)Shared.configuration).detail; } @SuppressWarnings("empty-statement") public void run() { Shared.traceInformation(getName(), Shared.getMessage("Starting")); scheduleStatistics(); while ((isInterrupted() == false) && (exit == false)) { try { if (Shared.isServerEnabled() == true) { update(); } } catch (Exception exception) { // exception.printStackTrace(); } try { sleep(60000); } catch (Exception exception) { } } if (scheduledFuture != null) scheduledFuture.cancel(true); Shared.traceInformation(getName(), Shared.getMessage("Finished")); } public long getLastDetection() { return(lastDetection); } @SuppressWarnings("empty-statement") private void update() throws Exception { while (readDetections() == true); { try{sleep(100);} catch (Exception e){}; } } private boolean readDetections() throws Exception { AccessEnforcement access = controller.getAccessEnforcement(); AccessEnforcementInformation information = access.getDeviceInformation(); Map mapTimestamps = new HashMap<>(); List detections = new ArrayList(); SimpleDateFormat formato1 = new SimpleDateFormat(Shared.getMessage("dd/MM/yyyy HH:mm:ss")); SimpleDateFormat formato2 = new SimpleDateFormat(Shared.getMessage("dd/MM/yyyy HH:mm:ss.SSS")); try { // Get detections for all cameras https Long lastDetectionTimestamp = lastDetection; if (lastDetectionTimestamp < 0) { lastDetectionTimestamp = Shared.controllerDetections.getLastDetection(access); if (lastDetectionTimestamp == 0) { lastDetectionTimestamp = formato1.parse("08/04/2024 00:00:00").getTime(); } } Calendar from = Calendar.getInstance(); from.setTimeInMillis(lastDetectionTimestamp + 1); Calendar to = Calendar.getInstance(); to.setTimeInMillis(System.currentTimeMillis()); // Update last detections timestamp for the camera List detectionsCamera = new ArrayList(); for (AccessEnforcementInformation_Neural_Lane lane : access.getDeviceInformation().neural.llane) { List detectionsCameraLane = readDetections(access, lane.number, from.getTimeInMillis(), to.getTimeInMillis()); if (detectionsCameraLane.size() > 0) detectionsCamera.addAll(detectionsCameraLane); } // Shared.println(this.getName(), "1.ReadDetections: " + detectionsCamera.size()); for (AccessEnforcement_Detection detection : detectionsCamera) { lastDetectionTimestamp = Math.max(lastDetectionTimestamp, detection.timestamp); detections.add(detection); } this.lastDetection = lastDetectionTimestamp; // Shared.println(this.getName(), "2.ReadDetections: " + detectionsCamera.size() + " - " + new Date(this.lastDetection).toString()); // Insert into database and update timestamps if (detections.size() > 0) { for (AccessEnforcement_Detection detection : detections) { try { // Shared.println(this.getName(), "3.ReadDetections Detection: " + detection); // Shared.println(this.getName(), "4.ReadDetections Detection: " + detection.images); // Shared.println(this.getName(), "5.ReadDetections Detection: " + detection.getLastState()); // Shared.println(this.getName(), "5.ReadDetections Detection: " + detection.getLastState().vehicle); if ((detection.images == null) || (detection.images.size() == 0)) { detection.images = getImagesDetectionUC(access, detection); } } catch (Exception e) { // Shared.printstack(this.getName(), e); } AccessEnforcement_Detection_State detectionState = detection.getLastState(); if ((detection.images != null) && (detection.images.size() >= 1)) { detectionState.state = AccessEnforcement_Detection_State.STATE_REVISION_PENDING; detectionState.timestamp = System.currentTimeMillis(); // Shared.printcorrect(getName(),Shared.getMessage("Successful (revision pending), plate") + " = " + detectionState.vehicle.plate + ", " + Shared.getMessage("date") + " = " + formato2.format(detection.timestamp)); } else { detectionState.state = AccessEnforcement_Detection_State.STATE_DISCARDED; detectionState.discarded = new AccessEnforcement_Detection_State_Discarded(); detectionState.discarded.code = AccessEnforcement_Detection_State_Discarded.DISCARDED_MISSING_PICTURES; detectionState.discarded.timestamp = System.currentTimeMillis(); detectionState.discarded.description = detectionState.discarded.getDescription(detectionState.discarded.code); // Shared.printerr(getName(),Shared.getMessage("Missing images, plate") + " = " + detectionState.vehicle.plate + ", " + Shared.getMessage("date") + " = " + formato2.format(detection.timestamp)); } this.controller.updateDatabaseDetection(information, detection); } counterDetections = counterDetections + detections.size(); return true; } } catch (Exception exception) { // Shared.printstack(getName(), exception); } return false; } private List readDetections(AccessEnforcement access, int lane, long from, long to) throws Exception { List detections = new ArrayList(); try { AccessEnforcementInformation information = access.getDeviceInformation(); // https://10.106.7.18/art?operation=getDetections&from=01/01/1970%2000:00:00&to=16/12/2023%2018:39:00&lane=1&limit=100&token=write,EdubVmde SimpleDateFormat formato1 = new SimpleDateFormat("dd/MM/yyyy"); SimpleDateFormat formato2 = new SimpleDateFormat("HH:mm:ss"); String url = "https://" + information.neural.connection.address + ":" + information.neural.connection.port + "/art?operation=getDetections"; url += "&from=" + formato1.format(from) + "%20" + formato2.format(from); url += "&to=" + formato1.format(to) + "%20" + formato2.format(to); url += "&lane=" + lane; url += "&limit=100"; String user = Shared.getText(information.neural.connection.user); String password = Shared.getText(information.neural.connection.password); if ((user == null) || (password == null)) { user = "write"; password = "EdubVmde"; } url += "&token=" + user + "," + password; // Shared.println(this.getName(), "1.URL GetDEtections: " + url); byte[] response = HttpsRequest.requestBytes(url, user, password, new byte[0], 30000, 60000); ErmDetection[] ucDetections = Serialization.deserialize(ErmDetection[].class, response); // Shared.println(this.getName(), "2.GetDEtections: " + ucDetections.length); for (ErmDetection ucDetection : ucDetections) { AccessEnforcement_Detection detection = new AccessEnforcement_Detection(); detection.device = access.getDeviceInformation(); detection.incidence = ucDetection.detection; detection.timestamp = ucDetection.timestamp; AccessEnforcement_Detection_State detectionState = new AccessEnforcement_Detection_State(); detectionState.timestamp = ucDetection.timestamp; detectionState.vehicle = new AccessEnforcement_Detection_State_Vehicle(); detectionState.vehicle.plate = ucDetection.plate.plate; detectionState.vehicle.confidence = ucDetection.plate.confidence; detectionState.vehicle.lane = ucDetection.lane; detection.states.add(detectionState); detections.add(detection); /* ucDetection.device = access.getDeviceInformation(); if (ucDetection.images != null) { for (AccessEnforcement_Detection_Image image : ucDetection.images) { try { OSD.osd(ucDetection, image, access.getDeviceInformation().getOSD(image.name)); } catch (Exception e) { Shared.printstack(this.getName(), e); } } } detections.add(ucDetection); */ } } catch (Exception e) { // Shared.printstack(this.getName(), e); } return detections; } /* private boolean getImagesDetection (AccessEnforcement access, AccessEnforcement_Detection detection) throws SerializationException, ServerException { Configuration configuration = (Configuration)Shared.configuration; try { SimpleDateFormat formatoImagen1 = new SimpleDateFormat(Shared.getMessage("yyyyMMdd")); SimpleDateFormat formatoImagen2 = new SimpleDateFormat(Shared.getMessage("HH")); SimpleDateFormat formatoImagen3 = new SimpleDateFormat(Shared.getMessage("yyyyMMddHHmmssSSS")); String deviceIdentifier = access.getIdentifier(); String path = configuration.detail.detections.storageFolder; File fpathImage = new File(path + "/" + deviceIdentifier + "/" + formatoImagen1.format(detection.timestamp) + formatoImagen2.format(detection.location.timestamp)); File filezip = new File(fpathImage.getAbsolutePath() + "/" + formatoImagen3.format(detection.location.timestamp) + ".zip"); File filesha = new File(fpathImage.getAbsolutePath() + "/" + formatoImagen3.format(detection.location.timestamp) + ".sha"); // Check first of all if images are in server disk // If there are not images then request to Erm and save to server disk if ((filezip.exists() == false) || (filesha.exists() == false)) { List detectionImages = getImagesDetectionUC(access, detection); detection.images.clear(); if (detectionImages.size() <= 1) { // Discard by no images Shared.discardDetection(Shared.configuration.general.language, detection, AccessEnforcement_Detection_State_Discarded.DISCARDED_MISSING_PICTURES); return(true); } // Save images to server disk saveImages(detection, configuration, filezip, filesha, detectionImages); detection.location.images.addAll(detectionImages); return(true); } } catch (Exception exception) { Shared.printstack(getName(), exception); } return(false); } */ private List getImagesDetectionUC(AccessEnforcement access, AccessEnforcement_Detection detection) throws Exception { List accessDetectionImages = new ArrayList(); try { // https://10.106.7.18/art?operation=getImage&incidence=22758&name=overview&token=write,EdubVmde // https://10.106.7.18/art?operation=getImage&incidence=22758&name=plate&token=write,EdubVmde String urlOverview = "https://" + access.getDeviceInformation().neural.connection.address + ":" + access.getDeviceInformation().neural.connection.port + "/art?operation=getImage"; urlOverview += "&incidence=" + detection.incidence; urlOverview += "&name=overview"; String user = Shared.getText(access.getDeviceInformation().neural.connection.user); String password = Shared.getText(access.getDeviceInformation().neural.connection.password); if ((user == null) || (password == null)) { user = "write"; password = "EdubVmde"; } urlOverview += "&token=" + user + "," + password; try { // Shared.println(this.getName(), "1.GetImages URLOver: " + urlOverview); byte[] response = HttpsRequest.requestBytes(urlOverview, user, password, new byte[0], 30000, 60000); // Shared.println(this.getName(), "2.GetImages URLOver: " + urlOverview); AccessEnforcement_Detection_Image imageOverview = new AccessEnforcement_Detection_Image(); imageOverview.format = "jpg"; imageOverview.name = "overview"; imageOverview.data = response; accessDetectionImages.add(imageOverview); } catch (Exception e) { } try { String urlPlate = "https://" + access.getDeviceInformation().neural.connection.address + ":" + access.getDeviceInformation().neural.connection.port + "/art?operation=getImage"; urlPlate += "&incidence=" + detection.incidence; urlPlate += "&name=plate"; urlPlate += "&token=" + user + "," + password; // Shared.println(this.getName(), "3.GetImages URLPlate: " + urlPlate); byte[] response = HttpsRequest.requestBytes(urlPlate, user, password, new byte[0], 30000, 60000); AccessEnforcement_Detection_Image imagePlate = new AccessEnforcement_Detection_Image(); imagePlate.format = "jpg"; imagePlate.name = "plate"; imagePlate.data = response; accessDetectionImages.add(imagePlate); // Shared.println(this.getName(), "4.GetImages URLPlate: " + imagePlate.data.length); } catch (Exception e) { } } catch (Exception e) { // Shared.printstack(this.getName(), e); throw e; } return accessDetectionImages; } /* private void saveImages(AccessEnforcement_Detection detection, Configuration configuration, File filezip, File filesha, List limages) throws SerializationException, ServerException { ByteArrayOutputStream bos = null; ZipOutputStream zos = null; try { CRC32 crc = new CRC32(); bos = new ByteArrayOutputStream(); zos = new ZipOutputStream(new BufferedOutputStream(bos), Licence.decrypt(configuration.detail.security.storagePassword).toCharArray()); ZipParameters zipParameters = new ZipParameters(); zipParameters.setCompressionMethod(CompressionMethod.DEFLATE); zipParameters.setCompressionLevel(CompressionLevel.FAST); zipParameters.setEncryptFiles(true); zipParameters.setEncryptionMethod(EncryptionMethod.AES); zipParameters.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_256); // Datection zip entry { byte[] data = Serialization.toPrettyString(detection).getBytes(); zipParameters.setFileNameInZip("detection.json"); crc.reset(); crc.update(data); zipParameters.setEntryCRC(crc.getValue()); zos.putNextEntry(zipParameters); zos.write(data); zos.closeEntry(); } for (AccessEnforcement_Detection_Image image : limages) { try { // Write zip entry { byte[] dataimage = image.data; zipParameters.setFileNameInZip(image.name + "." + image.format); crc.reset(); crc.update(dataimage); zos.putNextEntry(zipParameters); zipParameters.setEntryCRC(crc.getValue()); zos.write(dataimage); zos.closeEntry(); } } catch (Exception exception) { Shared.printstack(getName(), exception); throw exception; } } bos.flush(); bos.close(); zos.flush(); zos.close(); byte[] zipdata = bos.toByteArray(); // Save zip { filezip.getParentFile().mkdirs(); Files.write(filezip.toPath(), zipdata); } // Save sha { MessageDigest messageDigest = MessageDigest.getInstance("SHA-512"); messageDigest.reset(); messageDigest.update(zipdata); String sha512 = DatatypeConverter.printHexBinary(messageDigest.digest()); Files.write(filesha.toPath(), sha512.getBytes()); } } catch (Exception exception) { Shared.traceError(getName(), Shared.getMessage("Save images"), exception); throw new SerializationException(Shared.getMessage(exception.getMessage()), exception); } finally { try { bos.close(); } catch (Exception e){}; try { zos.close(); } catch (Exception e){}; } } */ private synchronized void scheduleStatistics() { long delay = 60000 - (System.currentTimeMillis() % 60000); ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1); scheduledFuture = scheduledExecutorService.scheduleAtFixedRate(new Runnable() { public void run() { // Shared.println(getName(), Shared.getMessage("Total detections in last minute") + " = " + counterDetections); counterDetections = 0; } }, delay, 60000, TimeUnit.MILLISECONDS); } }