package ch.hevs.isi.db; import ch.hevs.isi.MinecraftController; import ch.hevs.isi.core.DataPoint; import ch.hevs.isi.core.DataPointListener; import ch.hevs.isi.core.FloatDataPoint; import ch.hevs.isi.utils.Utility; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Properties; public class DatabaseConnector implements DataPointListener { private final Properties properties = new Properties(); // Properties of the config.properties file private URL urlForWrite = null; // URL of the InfluxDB server private HttpURLConnection con = null; // Connection to the InfluxDB server private boolean initialized = false; // Boolean to know if the database connector is initialized private final TimeManager _timeManager = new TimeManager(3); // Time manager to manage the time of the data points private long _timestamp = 0; // Timestamp of the data points public static String token = System.getenv("SECRET_TOKEN"); // Token to access the InfluxDB server public static String url = null; // URL of the InfluxDB server public static String org = null; // Organization of the InfluxDB server public static String bucket = null; // Bucket of the InfluxDB server private static DatabaseConnector mySelf = null; /** * Private constructor of the database connector * Read the config.properties file and initialize the database connector */ private DatabaseConnector (){ // Read the config.properties file /* try (InputStream input = Files.newInputStream(Paths.get("config.properties"))) { properties.load(input); } catch (Exception e) { e.printStackTrace(); } // Get the URL, the organization and the bucket from the config.properties file if their are null if (url == null){ url = properties.getProperty("DB.URL"); } if (org == null){ org = properties.getProperty("DB.ORG"); } if (bucket == null){ bucket = properties.getProperty("DB.BUCKET"); } */ // Subscribe to the update of DataPoints DataPointListener.subscribeUpdate(this); } /** * Get the instance of the database connector * @return The instance of the database connector */ public static DatabaseConnector getMySelf(){ if (mySelf == null){ mySelf = new DatabaseConnector(); } return mySelf; } /** * Initialize the database connector * @param url URL of the database. If null take the URL from the config.properties file */ public void initialize(String url){ // Full URL of the InfluxDB server String fullURL; try{ if(urlForWrite == null){ /* if(url == null){ url = properties.getProperty("DB.URL"); } */ fullURL = url + "/api/v2/write?org=" + org + "&bucket=" + bucket; Utility.pDebug("URL: " + fullURL); urlForWrite = new URL(fullURL); } initialized = true; } catch (MalformedURLException e) { throw new RuntimeException(e); } // If the user want to erase the previous data in the database // Delete the previous data if(MinecraftController.ERASE_PREVIOUS_DATA_INB_DB){ try { // Create the URL to delete the data fullURL = url + "/api/v2/delete?org=" + org + "&bucket=" + bucket; Utility.pDebug("URL: " + fullURL); URL urlForDelete = new URL(fullURL); // Create the connection to the database con = (HttpURLConnection) urlForDelete.openConnection(); con.setRequestMethod("POST"); con.setRequestProperty("Authorization", "Token " + token); con.setRequestProperty("Content-Type", "text/plain"); con.setRequestProperty("Accept", "application/json"); con.setDoOutput(true); } catch (IOException e) { throw new RuntimeException(e); } // Create the data to send to delete the data in the database and send it String data = "{\n"; data += "\"start\": \"2000-01-01T00:00:00Z\",\n"; data += "\"stop\": \"2024-04-25T10:45:00Z\",\n"; data += "\"predicate\": \"_measurement=\\\"Minecraft\\\"\"\n"; data += "}"; Utility.pDebug(data); sendDataToDatabase(data); } } /** * Add the timestamp to the data point * @param dp Data point to add the timestamp */ private void pushToDatabase(DataPoint dp) { // Initialize the database connector if not already done if(!initialized){ initialize(null); } // Create the data to send String data = "Minecraft "; data += dp.toString(); data += " " + _timestamp; // Send the data to the database sendDataToDatabase(data); } /** * Create and formate the request to send to the database * Send the request to the database * Check if the data is correctly send to the database with the response code * @param data Data to send to the database */ private void sendDataToDatabase(String data){ try { // Create connection and set headers if(con == null){ con = (HttpURLConnection) urlForWrite.openConnection(); con.setRequestMethod("POST"); con.setRequestProperty("Authorization", "Token " + token); con.setRequestProperty("Content-Type", "application/json"); con.setDoOutput(true); } // Send data OutputStreamWriter writer = new OutputStreamWriter(con.getOutputStream()); writer.write(data); writer.flush(); // Get response code int respondCode = con.getResponseCode(); if(respondCode != 204){ System.out.println("Error: " + respondCode + ", Data: " + data); } else { Utility.pDebug(data + " -> Database"); } con.disconnect(); con = null; } catch (IOException e) { e.printStackTrace(); } } /** * Push the data point to the database * @param dp Data point to push */ @Override public void onNewValue(DataPoint dp) { if(dp.getLabel().equals("CLOCK_FLOAT")) { FloatDataPoint fdp = (FloatDataPoint) dp; _timeManager.setTimestamp(fdp.getValue()); _timestamp = _timeManager.getNanosForDB(); } if(_timestamp != 0){ pushToDatabase(dp); } } }