package art.servers.gost.access.controller;
|
|
import art.library.interop.serialization.Serialization;
|
import art.library.interop.serialization.SerializationException;
|
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.servers.controller.Controller;
|
import art.servers.gost.access.Shared;
|
import art.servers.gost.access.configuration.Configuration;
|
import art.servers.gost.access.configuration.ConfigurationDetail;
|
import art.servers.gost.access.utils.OSD;
|
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 extends Controller
|
{
|
private Controller_ACCESS_Neural 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(Controller_ACCESS_Neural 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
|
{
|
System.out.println(getName() + " - 1.RUN");
|
if (Shared.isServerEnabled() == true)
|
{
|
System.out.println(getName() + " - 2.RUN");
|
update();
|
System.out.println(getName() + " - 3.RUN");
|
}
|
}
|
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);
|
}
|
|
|
|
private boolean readDetections() throws Exception
|
{
|
AccessEnforcement access = controller.getAccessEnforcement();
|
AccessEnforcementInformation information = access.getDeviceInformation();
|
Map<Integer, Long> mapTimestamps = new HashMap<>();
|
List<AccessEnforcement_Detection> detections = new ArrayList<AccessEnforcement_Detection>();
|
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<AccessEnforcement_Detection> detectionsCamera = new ArrayList<AccessEnforcement_Detection>();
|
for (AccessEnforcementInformation_Neural_Lane lane : access.getDeviceInformation().neural.llane)
|
{
|
List<AccessEnforcement_Detection> detectionsCameraLane = readDetections(access, lane.number, from.getTimeInMillis(), to.getTimeInMillis());
|
if (detectionsCameraLane.size() > 0) detectionsCamera.addAll(detectionsCameraLane);
|
}
|
|
for (AccessEnforcement_Detection detection : detectionsCamera)
|
{
|
lastDetectionTimestamp = Math.max(lastDetectionTimestamp, detection.timestamp);
|
detections.add(detection);
|
}
|
|
this.lastDetection = lastDetectionTimestamp;
|
|
|
// Insert into database and update timestamps
|
|
if (detections.size() > 0)
|
{
|
for (AccessEnforcement_Detection detection : detections)
|
{
|
try
|
{
|
if ((detection.images == null) || (detection.images.size() == 0))
|
{
|
getImagesDetectionUC(access, detection);
|
}
|
}
|
catch (Exception e)
|
{
|
Shared.printstack(this.getName(), e);
|
}
|
|
|
AccessEnforcement_Detection_State detectionState = detection.getLastState();
|
|
if ((detection.images != null) && (detection.images.size() >= 2))
|
{
|
if (Shared.controllerDetections.hasPermission(detection, detectionState.vehicle.plate) != null)
|
{
|
detectionState.state = AccessEnforcement_Detection_State.STATE_DISCARDED;
|
detectionState.discarded = new AccessEnforcement_Detection_State_Discarded();
|
detectionState.discarded.code = AccessEnforcement_Detection_State_Discarded.DISCARDED_ALLOWED;
|
detectionState.discarded.timestamp = System.currentTimeMillis();
|
detectionState.discarded.user = Shared.getApplicationName();
|
Shared.printcorrect(getName(),Shared.getMessage("Successful (allowed), plate") + " = " + detectionState.vehicle.plate + ", " + Shared.getMessage("date") + " = " + formato2.format(detection.timestamp));
|
}
|
else if ((this.detail.detections != null) && (detectionState.vehicle.confidence.floatValue() < this.detail.detections.plateConfidence) &&
|
(this.detail.detections.enabled == true))
|
{
|
detectionState.state = AccessEnforcement_Detection_State.STATE_DISCARDED;
|
detectionState.discarded = new AccessEnforcement_Detection_State_Discarded();
|
detectionState.discarded.code = AccessEnforcement_Detection_State_Discarded.DISCARDED_LOW_OCR_CONFIDENCE;
|
detectionState.discarded.timestamp = System.currentTimeMillis();
|
detectionState.discarded.user = Shared.getApplicationName();
|
Shared.printerr(getName(),Shared.getMessage("Low ocr confidence, plate") + " = " + detectionState.vehicle.plate + ", " + Shared.getMessage("confidence") + " = " + detectionState.vehicle.confidence.floatValue() + ", " + Shared.getMessage("date") + " = " + formato2.format(detection.timestamp));
|
}
|
else
|
{
|
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<AccessEnforcement_Detection> readDetections(AccessEnforcement access, int lane, long from, long to) throws Exception
|
{
|
List<AccessEnforcement_Detection> detections = new ArrayList<AccessEnforcement_Detection>();
|
|
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 + "/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(), "URL: " + url);
|
byte[] response = HttpsRequest.requestBytes(url, user, password, new byte[0], 30000, 60000);
|
AccessEnforcement_Detection[] ucDetections = Serialization.deserialize(AccessEnforcement_Detection[].class, response);
|
|
for (AccessEnforcement_Detection ucDetection : ucDetections)
|
{
|
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)
|
{
|
e.printStackTrace();
|
}
|
}
|
}
|
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<AccessEnforcement_Detection_Image> 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<AccessEnforcement_Detection_Image> getImagesDetectionUC(AccessEnforcement access, AccessEnforcement_Detection detection) throws Exception
|
{
|
List<AccessEnforcement_Detection_Image> accessDetectionImages = new ArrayList<AccessEnforcement_Detection_Image>();
|
|
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 + "/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;
|
byte[] response = HttpsRequest.requestBytes(urlOverview, user, password, new byte[0], 30000, 60000);
|
|
AccessEnforcement_Detection_Image imageOverview = new AccessEnforcement_Detection_Image();
|
imageOverview.format = "jpg";
|
imageOverview.name = "overview";
|
imageOverview.data = response;
|
accessDetectionImages.add(imageOverview);
|
|
String urlPlate = "https://" + access.getDeviceInformation().neural.connection.address + "/art?operation=getImage";
|
urlPlate += "&incidence=" + detection.incidence;
|
urlPlate += "&name=plate";
|
urlPlate += "&token=" + user + "," + password;
|
|
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);
|
}
|
catch (SerializationException e)
|
{
|
if (e.getMessage().indexOf("NoSuchFileException") < 0)
|
{
|
throw e;
|
}
|
}
|
catch (Exception e)
|
{
|
throw e;
|
}
|
|
return accessDetectionImages;
|
}
|
|
|
/*
|
private void saveImages(AccessEnforcement_Detection detection, Configuration configuration, File filezip, File filesha, List<AccessEnforcement_Detection_Image> 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);
|
}
|
|
}
|