Alejandro Acuña
2024-07-30 65a64a81d30f00f1fffd5da6866850e1308e1135
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
package art.servers.gost.access.controller;
 
import art.library.interop.serialization.Serialization;
import art.library.model.devices.Device;
import art.library.model.devices.gost.access.AccessEnforcement;
import art.library.model.devices.gost.access.AccessEnforcementInformation;
import art.library.model.devices.gost.access.types.AccessEnforcement_Detection;
import art.library.model.devices.gost.access.types.AccessEnforcement_Detection_State;
import art.library.utils.licence.Licence;
import art.servers.controller.ControllerDevice;
import art.servers.gost.access.Shared;
import art.servers.gost.access.types.DatabasePoolConnection;
import art.servers.gost.access.utils.ZIP;
import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Timestamp;
import java.sql.Types;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import org.postgresql.util.PGobject;
 
 
public class Controller_ACCESS extends ControllerDevice
{
    protected DatabasePoolConnection database = null;
 
        
    public Controller_ACCESS(Device device, DatabasePoolConnection database)
    {
        super(device);
        this.database = database;
    }
 
 
 
    protected void initialise()
    {
        // Database
        
        Connection connection = null;
 
        try
        {
            connection = database.getConnection(true);
            
            database.executeUpdate(connection, "CREATE TABLE IF NOT EXISTS detections(number BIGSERIAL, datetime TIMESTAMP, "
                    + "device TEXT, type TEXT, plate TEXT NOT NULL, state SMALLINT, record TEXT, value JSONB, "
                    + "PRIMARY KEY (datetime, device, plate)) "
                    + "PARTITION BY RANGE (datetime)");
            database.executeUpdate(connection, "CREATE INDEX IF NOT EXISTS detections_index_1 ON detections (number)");
            database.executeUpdate(connection, "CREATE INDEX IF NOT EXISTS detections_index_2 ON detections (datetime)");
            database.executeUpdate(connection, "CREATE INDEX IF NOT EXISTS detections_index_3 ON detections (datetime, device)");
            database.executeUpdate(connection, "CREATE INDEX IF NOT EXISTS detections_index_4 ON detections (datetime, type)");
            database.executeUpdate(connection, "CREATE INDEX IF NOT EXISTS detections_index_6 ON detections (datetime, state)");
            database.executeUpdate(connection, "CREATE INDEX IF NOT EXISTS detections_index_7 ON detections (datetime, plate)");
            database.executeUpdate(connection, "CREATE INDEX IF NOT EXISTS detections_index_8 ON detections (datetime, record");
            database.executeUpdate(connection, "CREATE INDEX IF NOT EXISTS detections_index_9 ON detections (record)");
            database.executeUpdate(connection, "CREATE INDEX IF NOT EXISTS detections_index_10 ON detections (state)");
            
            
            // Partitioned table 
            
            SimpleDateFormat formato1 = new SimpleDateFormat("yyyy_MM");
            SimpleDateFormat formato2 = new SimpleDateFormat("yyyy-MM-dd");
 
            Calendar calendar1 = Calendar.getInstance();
            calendar1.setTimeInMillis(System.currentTimeMillis());
            calendar1.set(Calendar.DATE, 1);
            calendar1.set(Calendar.HOUR_OF_DAY, 0);
            calendar1.set(Calendar.MINUTE, 0);
            calendar1.set(Calendar.SECOND, 0);
            calendar1.set(Calendar.MILLISECOND, 0);
            calendar1.add(Calendar.MONTH, -24);
 
            Calendar calendar2 = Calendar.getInstance();
            calendar2.setTimeInMillis(calendar1.getTimeInMillis());
            calendar2.add(Calendar.MONTH, 1);
 
            for (int i=0; i<48; i++)
            {
                String tablename = "detections_" + formato1.format(calendar1.getTimeInMillis());
                String month1 = formato2.format(calendar1.getTimeInMillis());
                String month2 = formato2.format(calendar2.getTimeInMillis());
 
                database.executeUpdate(connection, "CREATE TABLE IF NOT EXISTS " + tablename + " PARTITION OF detections FOR VALUES FROM ('" + month1 + "') TO ('" + month2 + "')");
                
                calendar1.add(Calendar.MONTH, 1);
                calendar2.add(Calendar.MONTH, 1);
            }
            
            
            database.vacuum("detections", connection);
            
        }
        catch (Exception exception)
        {
            // Shared.printstack(getName(), exception);
            Shared.traceError(getName(),Shared.getMessage("Initialise"), exception); 
        }
        finally
        {
            database.releaseConnection(connection);
        }        
    }    
 
    
 
    
    protected int updateDatabaseDetection(AccessEnforcementInformation deviceInformation, AccessEnforcement_Detection detection) throws Exception
    {
        Connection connection = null;
        PreparedStatement statement  = null;
        ResultSet resultset  = null;
        
        try
        {
            connection = database.getConnection(true);
            
            // Exists
            {
                String command = "SELECT EXISTS(SELECT 1 FROM  detections WHERE datetime = ? AND device = ?)";
                statement = connection.prepareStatement(command);
                statement.setTimestamp(1, new Timestamp(detection.timestamp));
                statement.setString(2, deviceInformation.getIdentifier());
                resultset = statement.executeQuery();
                resultset.next();
                if (resultset.getBoolean(1) == true) return 0;
            }
            
            
            // Save images
 
            ZIP.zip(detection, Licence.decrypt(deviceInformation.storage.storagePassword), deviceInformation.storage.storageFolder);
 
            // Remove images, we don't want store in database
 
            detection.images = null;
 
            AccessEnforcement_Detection_State detectionState = detection.getLastState();
            if (detectionState.vehicle.plate != null) detectionState.vehicle.plate = detectionState.vehicle.plate.replaceAll("\\s+","");
                    
            // Insert
            {
                String command = "INSERT INTO detections (datetime, device, type, plate, state, record , value) VALUES (?,?,?,?,?,?,?) ON CONFLICT DO NOTHING";
                statement = connection.prepareStatement(command);
                PGobject jsonObject = new PGobject();
                jsonObject.setType("json");
                jsonObject.setValue(Serialization.toString(detection));
 
                statement.setTimestamp(1, new Timestamp(detection.timestamp));
                statement.setString(2, deviceInformation.getIdentifier());
                statement.setString(3, AccessEnforcement.class.getName());
                statement.setString(4, detectionState.vehicle.getPlate());
                statement.setShort(5, detectionState.state);
 
                if ((detectionState.violation != null) && (detectionState.violation.record != null))
                {
                    statement.setString(6, detectionState.violation.record);
                }
                else
                {
                    statement.setNull(6, Types.VARCHAR);
                }
 
                statement.setObject(7, jsonObject);
                int result = statement.executeUpdate();
                database.close(statement);
                return result;
            }
        }
        finally
        {
            database.releaseConnection(connection, statement);
        }
 
    }
    
    
    
    
    
    
    protected void delete(File folder) 
    {
        for (File file : folder.listFiles())
        {
            if (file.isDirectory() == true)
            {
                delete(file);
            }
            else
            {
                file.delete();
            }
        }
        
        folder.delete();
    }    
    
}