Database revolution
- added in fitbitData an interface for keeping track of date - removed annoying IOException, now will write a LOG - same thing in sensor - fixed main and adapted to new Database system - Database now has Local or Remote (to implement)
This commit is contained in:
@@ -85,7 +85,7 @@ public class Fitbit {
|
|||||||
* @return un intero rappresentante i passi effettuati
|
* @return un intero rappresentante i passi effettuati
|
||||||
* @throws IOException nel caso la richiesta non vada a buon fine
|
* @throws IOException nel caso la richiesta non vada a buon fine
|
||||||
*/
|
*/
|
||||||
public synchronized int getSteps() throws IOException {
|
public synchronized int getSteps() {
|
||||||
steps = update(Steps.class, steps, "1" + USER + "activities/steps/date/today/1w.json");
|
steps = update(Steps.class, steps, "1" + USER + "activities/steps/date/today/1w.json");
|
||||||
return steps.getSteps();
|
return steps.getSteps();
|
||||||
}
|
}
|
||||||
@@ -97,7 +97,7 @@ public class Fitbit {
|
|||||||
* @return un intero rappresentante la media del battito cardiaco degli ultimi 15 minuti
|
* @return un intero rappresentante la media del battito cardiaco degli ultimi 15 minuti
|
||||||
* @throws IOException nel caso la richiesta non vada a buon fine
|
* @throws IOException nel caso la richiesta non vada a buon fine
|
||||||
*/
|
*/
|
||||||
public synchronized double getHeartRate() throws IOException { return getHeartRate(15); }
|
public synchronized double getHeartRate() { return getHeartRate(15); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ricevi il battito cardiaco dell'utente<br>
|
* Ricevi il battito cardiaco dell'utente<br>
|
||||||
@@ -107,7 +107,7 @@ public class Fitbit {
|
|||||||
* @return un intero rappresentante la media del battito cardiaco degli ultimi minuti specificati
|
* @return un intero rappresentante la media del battito cardiaco degli ultimi minuti specificati
|
||||||
* @throws IOException nel caso la richiesta non vada a buon fine
|
* @throws IOException nel caso la richiesta non vada a buon fine
|
||||||
*/
|
*/
|
||||||
public synchronized double getHeartRate(int lastMinutes) throws IOException {
|
public synchronized double getHeartRate(int lastMinutes) {
|
||||||
if(lastMinutes<=0)
|
if(lastMinutes<=0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@ public class Fitbit {
|
|||||||
* @return un intero rappresentante le ore passate a dormire
|
* @return un intero rappresentante le ore passate a dormire
|
||||||
* @throws IOException nel caso la richiesta non vada a buon fine
|
* @throws IOException nel caso la richiesta non vada a buon fine
|
||||||
*/
|
*/
|
||||||
public synchronized long getHoursSleep() throws IOException {
|
public synchronized long getHoursSleep() {
|
||||||
sleep = update(Sleep.class, sleep,"1.2" + USER + "sleep/date/today.json");
|
sleep = update(Sleep.class, sleep,"1.2" + USER + "sleep/date/today.json");
|
||||||
return sleep.getMinutesAsleep()/60;
|
return sleep.getMinutesAsleep()/60;
|
||||||
}
|
}
|
||||||
@@ -143,7 +143,7 @@ public class Fitbit {
|
|||||||
* @return una lista contenente ogni volta che l'utente ha dormito
|
* @return una lista contenente ogni volta che l'utente ha dormito
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public synchronized List<Sleep.SleepData> getDetailedSleep() throws IOException {
|
public synchronized List<Sleep.SleepData> getDetailedSleep() {
|
||||||
sleep = update(Sleep.class, sleep,"1.2" + USER + "sleep/date/today.json");
|
sleep = update(Sleep.class, sleep,"1.2" + USER + "sleep/date/today.json");
|
||||||
return sleep.getDatas();
|
return sleep.getDatas();
|
||||||
}
|
}
|
||||||
@@ -151,14 +151,15 @@ public class Fitbit {
|
|||||||
/**
|
/**
|
||||||
* Semplice funzione che controlla che si possa fare l'update o meno di una specifica classe.<br>
|
* Semplice funzione che controlla che si possa fare l'update o meno di una specifica classe.<br>
|
||||||
* Se e' possibile fare l'update viene mandata una run all'url selezionato e viene ritornata la variabile aggiornata<br>
|
* Se e' possibile fare l'update viene mandata una run all'url selezionato e viene ritornata la variabile aggiornata<br>
|
||||||
* Altrimenti viene ritornata la variabile passata
|
* Altrimenti viene ritornata la variabile passata<br>
|
||||||
|
* Nel caso di fallimento della richiesta varra' restituito la variabile passata in input
|
||||||
*
|
*
|
||||||
* @param varClass la classe della variabile passata
|
* @param varClass la classe della variabile passata
|
||||||
* @param variable la variabile che deve fare l'update (passando null si forza la richiesta)
|
* @param variable la variabile che deve fare l'update (passando null si forza la richiesta)
|
||||||
* @param url l'url da cui prende i dati aggiornati
|
* @param url l'url da cui prende i dati aggiornati
|
||||||
* @return la variabile aggiornata
|
* @return la variabile aggiornata
|
||||||
*/
|
*/
|
||||||
private synchronized <T> T update(Class<T> varClass, T variable, String url) throws IOException {
|
private synchronized <T> T update(Class<T> varClass, T variable, String url) {
|
||||||
try {
|
try {
|
||||||
long current = System.currentTimeMillis();
|
long current = System.currentTimeMillis();
|
||||||
long latest = latestRequest.get(varClass);
|
long latest = latestRequest.get(varClass);
|
||||||
@@ -168,10 +169,16 @@ public class Fitbit {
|
|||||||
return variable;
|
return variable;
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
// do nothing and update
|
// do nothing and update
|
||||||
|
} finally {
|
||||||
|
LOG.info("Updating " + varClass.getSimpleName() + " form " + BASIC_URL + url);
|
||||||
|
try {
|
||||||
|
variable = auth.run(BASIC_URL + url, varClass);
|
||||||
|
latestRequest.put(varClass, System.currentTimeMillis());
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.error("Non sono riuscito a prender i dati aggiornati: " + e.getMessage());
|
||||||
|
}
|
||||||
|
return variable;
|
||||||
}
|
}
|
||||||
latestRequest.put(varClass, System.currentTimeMillis());
|
|
||||||
LOG.info("Updating " + varClass.getSimpleName() + " form " + BASIC_URL + url);
|
|
||||||
return auth.run(BASIC_URL + url, varClass);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -92,16 +92,17 @@ public class Sensor {
|
|||||||
/**
|
/**
|
||||||
* Fa in modo di forzare l'aggiornamento dei dispositivi
|
* Fa in modo di forzare l'aggiornamento dei dispositivi
|
||||||
* @param timeout fa aspettare un tot di tempo prima di provare a forzare e dopo l'aggiornameto
|
* @param timeout fa aspettare un tot di tempo prima di provare a forzare e dopo l'aggiornameto
|
||||||
* @throws InterruptedException nel caso che succeda qualcosa
|
|
||||||
*/
|
*/
|
||||||
synchronized public void update(int timeout) throws InterruptedException {
|
synchronized public void update(int timeout) {
|
||||||
wait(timeout);
|
try {
|
||||||
for (Device device : devices.getAllDevices())
|
wait(timeout / 2);
|
||||||
try {
|
for (Device device : devices.getAllDevices())
|
||||||
device.update();
|
try {
|
||||||
} catch (Exception e) {}
|
device.update();
|
||||||
|
} catch (Exception e) { }
|
||||||
|
|
||||||
wait(timeout);
|
wait(timeout / 2);
|
||||||
|
} catch (InterruptedException e) { }
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
public boolean IsLowLuminescence(int Luminescence) {
|
public boolean IsLowLuminescence(int Luminescence) {
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
package device.fitbitdata;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
public class Device {
|
|
||||||
|
|
||||||
public String lastSyncTime;
|
|
||||||
|
|
||||||
// @JsonProperty ("lastSyncTime")
|
|
||||||
public String getLastSyncTime(List<Map<String,String>> sync){
|
|
||||||
lastSyncTime = null;
|
|
||||||
for(Map<String, String > d: sync) {
|
|
||||||
String temp = d.get("lastSyncTime");
|
|
||||||
if ((lastSyncTime == null) || (lastSyncTime.compareTo(temp) < 0))
|
|
||||||
lastSyncTime = temp;
|
|
||||||
}
|
|
||||||
return lastSyncTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
8
src/main/java/device/fitbitdata/FitbitData.java
Normal file
8
src/main/java/device/fitbitdata/FitbitData.java
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package device.fitbitdata;
|
||||||
|
|
||||||
|
public abstract class FitbitData {
|
||||||
|
private long millisec = 0;
|
||||||
|
|
||||||
|
public void setDate(long millisec) { this.millisec = millisec; }
|
||||||
|
public long getDate() { return this.millisec; }
|
||||||
|
}
|
||||||
@@ -7,12 +7,10 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public class HeartRate {
|
public class HeartRate extends FitbitData {
|
||||||
|
|
||||||
private double average;
|
private double average;
|
||||||
|
|
||||||
public double getAverage() { return average; }
|
|
||||||
|
|
||||||
@JsonProperty("activities-heart-intraday")
|
@JsonProperty("activities-heart-intraday")
|
||||||
public void setAverage(Map<String, Object> map) {
|
public void setAverage(Map<String, Object> map) {
|
||||||
List<Map> data = (List) map.get("dataset");
|
List<Map> data = (List) map.get("dataset");
|
||||||
@@ -25,4 +23,7 @@ public class HeartRate {
|
|||||||
if(data.size() == 0)
|
if(data.size() == 0)
|
||||||
average = 0;
|
average = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setAverage(double average) { this.average = average; }
|
||||||
|
public double getAverage() { return average; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,14 +49,12 @@ public class Sleep {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class SleepData {
|
public class SleepData {
|
||||||
public final Timestamp start_date;
|
public final long start_date;
|
||||||
public final long duration;
|
public final long duration;
|
||||||
public final Timestamp end_date;
|
|
||||||
|
|
||||||
public SleepData(Date start_date, long duration) {
|
public SleepData(Date start_date, long duration) {
|
||||||
this.start_date = new Timestamp(start_date.getTime());
|
this.start_date = start_date.getTime();
|
||||||
this.duration = duration;
|
this.duration = duration;
|
||||||
this.end_date = start_date!=null? new Timestamp(start_date.getTime() + duration):null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
|||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public class Steps {
|
public class Steps extends FitbitData {
|
||||||
|
|
||||||
private int steps=0;
|
private int steps = 0;
|
||||||
|
|
||||||
@JsonProperty("activities-steps")
|
@JsonProperty("activities-steps")
|
||||||
public void setSteps(Map<String, String>[] array) {
|
public void setSteps(Map<String, String>[] array) {
|
||||||
@@ -22,7 +22,7 @@ public class Steps {
|
|||||||
if(map.get("dateTime").equals(strDate))
|
if(map.get("dateTime").equals(strDate))
|
||||||
steps = Integer.parseInt(map.get("value"));
|
steps = Integer.parseInt(map.get("value"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSteps() { return steps; }
|
|
||||||
|
|
||||||
|
public void setSteps(int steps) { this.steps = steps; }
|
||||||
|
public int getSteps() { return steps; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
package main;
|
package main;
|
||||||
|
|
||||||
import device.*;
|
import device.*;
|
||||||
|
import device.fitbitdata.HeartRate;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import support.Database;
|
import support.database.Database;
|
||||||
|
import support.database.LocalDB;
|
||||||
|
import support.database.RemoteDB;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@@ -28,6 +28,7 @@ public class Main {
|
|||||||
private static Hue lights = null;
|
private static Hue lights = null;
|
||||||
private static Fitbit fitbit = null;
|
private static Fitbit fitbit = null;
|
||||||
private static Sensor sensor = null;
|
private static Sensor sensor = null;
|
||||||
|
private static Database database = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Funzione principale, qui si creano tutte le classi che verranno utilizzate.<br>
|
* Funzione principale, qui si creano tutte le classi che verranno utilizzate.<br>
|
||||||
@@ -39,8 +40,9 @@ public class Main {
|
|||||||
* <li>hueUser</li>
|
* <li>hueUser</li>
|
||||||
* <li>sensorNode</li>
|
* <li>sensorNode</li>
|
||||||
* <li>sensorLog</li>
|
* <li>sensorLog</li>
|
||||||
|
* <li>remoteDb</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* @param args per ora nulla, ma forse in futuro si potrebbe mettere roba
|
* @param args
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
Map<String, String> arguments = getArgsMap(args);
|
Map<String, String> arguments = getArgsMap(args);
|
||||||
@@ -50,6 +52,7 @@ public class Main {
|
|||||||
String hueUser = arguments.get("hueUser");
|
String hueUser = arguments.get("hueUser");
|
||||||
Integer sensorLog = getInt(arguments.get("sensorLog"));
|
Integer sensorLog = getInt(arguments.get("sensorLog"));
|
||||||
Integer sensorNode = getInt(arguments.get("sensorNode"));
|
Integer sensorNode = getInt(arguments.get("sensorNode"));
|
||||||
|
String remoteDbUrl = arguments.get("remoteDb");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
LOG.info("Connessione alle Philips Hue...");
|
LOG.info("Connessione alle Philips Hue...");
|
||||||
@@ -70,6 +73,9 @@ public class Main {
|
|||||||
LOG.info("Connessione al Fitbit, ignorare eventuale errore per setPermissionsToOwnerOnly...");
|
LOG.info("Connessione al Fitbit, ignorare eventuale errore per setPermissionsToOwnerOnly...");
|
||||||
fitbit = new Fitbit();
|
fitbit = new Fitbit();
|
||||||
|
|
||||||
|
LOG.info("Connessione al database...");
|
||||||
|
database = remoteDbUrl==null? new LocalDB():new RemoteDB(remoteDbUrl);
|
||||||
|
|
||||||
startInsertData();
|
startInsertData();
|
||||||
startCheckSteps();
|
startCheckSteps();
|
||||||
startHueControlledByHeartBeat();
|
startHueControlledByHeartBeat();
|
||||||
@@ -121,10 +127,8 @@ public class Main {
|
|||||||
*/
|
*/
|
||||||
private static void startInsertData() {
|
private static void startInsertData() {
|
||||||
try {
|
try {
|
||||||
Database database = Database.getInstance();
|
Thread hourlyData = Database.insertHourlyDataIn(database, fitbit, 5);
|
||||||
|
Thread dailyData = Database.insertDailyData(database, fitbit, 5);
|
||||||
Thread hourlyData = new Thread(database.insertHourlyData(fitbit), "updating-hour-data");
|
|
||||||
Thread dailyData = new Thread(database.insertDailyData(fitbit), "updating-day-data");
|
|
||||||
|
|
||||||
LOG.info("Starting threads for automatic update");
|
LOG.info("Starting threads for automatic update");
|
||||||
hourlyData.start();
|
hourlyData.start();
|
||||||
@@ -138,24 +142,18 @@ public class Main {
|
|||||||
/**
|
/**
|
||||||
* funzione che logga periodicalmente i valori ricevuti dal sensore
|
* funzione che logga periodicalmente i valori ricevuti dal sensore
|
||||||
*/
|
*/
|
||||||
private static void startSensorLog(int seconds) {
|
private static void startSensorLog(int minutes) {
|
||||||
Thread thread = new Thread(new Runnable() {
|
LOG.info("Starting thread for logging sensor data");
|
||||||
|
|
||||||
|
Runnable runnable = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public synchronized void run() {
|
public synchronized void run() {
|
||||||
boolean notInterrupted = true;
|
sensor.update(0);
|
||||||
while(notInterrupted) {
|
LOG.info("Luminosita' rilevata: " + sensor.getBrightnessLevel());
|
||||||
try {
|
|
||||||
sensor.update((seconds/2) * 1000);
|
|
||||||
LOG.info("Luminosita' rilevata: " + sensor.getBrightnessLevel());
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
notInterrupted = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, "sensor");
|
};
|
||||||
|
|
||||||
thread.start();
|
Database.getThreadStartingEach(runnable, "sensor", minutes).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO AUTO:{B} Gestione luci in modo che la luminosità sia sempre la stessa
|
// TODO AUTO:{B} Gestione luci in modo che la luminosità sia sempre la stessa
|
||||||
@@ -172,7 +170,6 @@ public class Main {
|
|||||||
boolean notInterrupted = true;
|
boolean notInterrupted = true;
|
||||||
Calendar calendar = Calendar.getInstance();
|
Calendar calendar = Calendar.getInstance();
|
||||||
while(notInterrupted) {
|
while(notInterrupted) {
|
||||||
calendar.setTimeInMillis(System.currentTimeMillis());
|
|
||||||
int bright = sensor.getBrightnessLevel();
|
int bright = sensor.getBrightnessLevel();
|
||||||
int hour = calendar.get(Calendar.HOUR_OF_DAY);
|
int hour = calendar.get(Calendar.HOUR_OF_DAY);
|
||||||
|
|
||||||
@@ -220,53 +217,42 @@ public class Main {
|
|||||||
// controllare che non differiscano di un valore Delta
|
// controllare che non differiscano di un valore Delta
|
||||||
// se differiscono di almeno Delta modificare le luci abbassandole o alzandole secondo le esigenze
|
// se differiscono di almeno Delta modificare le luci abbassandole o alzandole secondo le esigenze
|
||||||
// (nel caso modificare anche il colore e renderlo meno intenso o di piu)
|
// (nel caso modificare anche il colore e renderlo meno intenso o di piu)
|
||||||
|
LOG.info("Starting thread lights for heartbeat");
|
||||||
|
final int minutes = 30;
|
||||||
|
final int delta = 15;
|
||||||
|
Runnable runnable = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public synchronized void run() {
|
||||||
|
int sum=0;
|
||||||
|
int count=0;
|
||||||
|
double average;
|
||||||
|
|
||||||
Calendar past = Calendar.getInstance();
|
List<HeartRate> heartRate = database.getHeartDataOfLast(15); //TODO da discriminare l'ora (mi sa che c'è da mettere mano al db
|
||||||
Database instance = Database.getInstance();
|
Calendar now = Calendar.getInstance();
|
||||||
int sum =0;
|
Calendar past = Calendar.getInstance();
|
||||||
int count =0;
|
now.setTimeInMillis(System.currentTimeMillis());
|
||||||
double avg =0;
|
|
||||||
Timestamp twoWeeksAgo ;
|
|
||||||
|
|
||||||
|
for(HeartRate rate: heartRate) {
|
||||||
while(true){
|
past.setTimeInMillis(rate.getDate());
|
||||||
|
if(past.get(Calendar.HOUR_OF_DAY) == now.get(Calendar.HOUR_OF_DAY)) {
|
||||||
past.setTimeInMillis(System.currentTimeMillis());
|
sum += rate.getAverage();
|
||||||
try {
|
count++;
|
||||||
|
}
|
||||||
past.add(Calendar.DAY_OF_YEAR, -15);
|
|
||||||
twoWeeksAgo = new Timestamp (past.getTimeInMillis());
|
|
||||||
|
|
||||||
ResultSet rs = instance.getDataFromDatabase("SELECT rate FROM heart WHERE day_hour > "+twoWeeksAgo); //TODO da discriminare l'ora (mi sa che c'è da mettere mano al db
|
|
||||||
|
|
||||||
while (rs.next()) {
|
|
||||||
sum += rs.getDouble("rate");
|
|
||||||
count ++;
|
|
||||||
}
|
}
|
||||||
|
average = count!=0? sum/count:0;
|
||||||
|
|
||||||
avg = sum/count;
|
double rateNow = fitbit.getHeartRate(minutes);
|
||||||
|
if ((rateNow-average) >= delta )
|
||||||
Fitbit fitBit = new Fitbit();
|
lights.decreaseBrightness();
|
||||||
double rateNow = fitBit.getHeartRate(30);
|
//avvisare con una voce registrata?
|
||||||
if ((rateNow-avg) >= 15 )
|
else if ((rateNow-average) <= -delta)
|
||||||
lights.decreaseBrightness();
|
//alzare le luci?
|
||||||
else if ((rateNow-avg) <=-15)
|
//avvisare con una voce registrata?
|
||||||
//alzare le luci?
|
;
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
Thread.sleep(1800000);
|
|
||||||
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
Database.getThreadStartingEach(runnable, "lights-with-heartbeat", minutes).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO AUTO:{D} Ad una certa ora guarda i passi e se sono pochi dillo
|
// TODO AUTO:{D} Ad una certa ora guarda i passi e se sono pochi dillo
|
||||||
@@ -299,7 +285,7 @@ public class Main {
|
|||||||
|
|
||||||
/A/ Dati del sonno/battito/passi che l'utente puo' richiedere
|
/A/ Dati del sonno/battito/passi che l'utente puo' richiedere
|
||||||
XXX Gestione luci secondo le esigenze dell'utente ( settare Dialogflow e server + risolvere bug )
|
XXX Gestione luci secondo le esigenze dell'utente ( settare Dialogflow e server + risolvere bug )
|
||||||
/C/ EXTRA Gestione musica tramite comando vocale
|
/C/ Gestione musica tramite comando vocale
|
||||||
|
|
||||||
// Randomly at night heavy metal start
|
// Randomly at night heavy metal start
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,190 +0,0 @@
|
|||||||
package support;
|
|
||||||
|
|
||||||
import device.Fitbit;
|
|
||||||
import device.fitbitdata.Sleep;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.sql.*;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Classe che si connette al database e permette di aggiornare i dati in modo automatico tramite dei runnable
|
|
||||||
*/
|
|
||||||
public class Database {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Un logger per scrivere a console eventuali errori o informazioni
|
|
||||||
*/
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Database.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Il percorso di dove trovare il database, strutturato in: <interfaccia>:<implementazione>:<percorso vero e proprio>
|
|
||||||
*/
|
|
||||||
public static final String DB_LOCATION = "jdbc:sqlite:";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Il nome del database (aka il nome del file)
|
|
||||||
*/
|
|
||||||
public static final String DB_NAME = "user_data.db";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Un calendario, visto che ci serve sapere quando inseriamo i dati
|
|
||||||
*/
|
|
||||||
private static final Calendar CALENDAR = Calendar.getInstance();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Una costante che indica quanti millisecondi ci sono in un minuto (utile per le conversioni)
|
|
||||||
*/
|
|
||||||
private static final int MINUTES_TO_MILLISEC = 60000;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* L'unica istanza del database (dato che e' una classe Singleton)
|
|
||||||
*/
|
|
||||||
private static Database instance;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* La connessione al database
|
|
||||||
*/
|
|
||||||
private final Connection conn;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Crea una connessione al Database specificato in DB_LOCATION e con il nome DB_NAME.
|
|
||||||
* Se il Database non esiste lo crea e inizializza anche delle tabelle:
|
|
||||||
* <ul>
|
|
||||||
* <li>'total' contiene i dati utente giorno per giorno.</li>
|
|
||||||
* <li>'heart' battito + orario</li>
|
|
||||||
* <li>'sleep' inizio + fine + durata</li>
|
|
||||||
* </ul>
|
|
||||||
* @throws SQLException se qualcosa e' andato storto
|
|
||||||
*/
|
|
||||||
private Database() throws SQLException {
|
|
||||||
CALENDAR.setTimeInMillis(System.currentTimeMillis());
|
|
||||||
conn = DriverManager.getConnection(DB_LOCATION + DB_NAME);
|
|
||||||
Statement statement = conn.createStatement();
|
|
||||||
statement.execute("CREATE TABLE IF NOT EXISTS total (day DATE PRIMARY KEY, sleep_time INTEGER, heart_rate DOUBLE, steps INTEGER)");
|
|
||||||
statement.execute("CREATE TABLE IF NOT EXISTS heart (day_hour DATE PRIMARY KEY, rate DOUBLE)");
|
|
||||||
statement.execute("CREATE TABLE IF NOT EXISTS sleep (sleep_start DATE PRIMARY KEY, sleep_end DATE, duration INTEGER)");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Crea una connessione al Database specificato in DB_LOCATION e con il nome DB_NAME.
|
|
||||||
* Se il Database non esiste lo crea e inizializza anche delle tabelle:
|
|
||||||
* <ul>
|
|
||||||
* <li>'total' contiene i dati utente giorno per giorno.</li>
|
|
||||||
* <li>'heart' battito + orario</li>
|
|
||||||
* <li>'sleep' inizio + fine + durata</li>
|
|
||||||
* </ul>
|
|
||||||
* <br>
|
|
||||||
* L'implementazione e' synchronized (si spera thread safe)
|
|
||||||
*/
|
|
||||||
public synchronized static Database getInstance() {
|
|
||||||
try {
|
|
||||||
instance = instance==null? new Database():instance;
|
|
||||||
} catch (SQLException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prendi il Runnable che automaticamente gestisce l'inserimento dei dati orari (per ora solo il battito cardiaco)<br>
|
|
||||||
* <br>
|
|
||||||
* Il runnable e' synchronized (si spera thread safe)
|
|
||||||
* @param fitbit la classe che contiene i dati aggiornati
|
|
||||||
* @return un Runnable
|
|
||||||
*/
|
|
||||||
public Runnable insertHourlyData(Fitbit fitbit) {
|
|
||||||
return new Runnable() {
|
|
||||||
@Override
|
|
||||||
public synchronized void run() {
|
|
||||||
boolean notInterrupted = true;
|
|
||||||
boolean retry = false;
|
|
||||||
double heartRate = 0;
|
|
||||||
Timestamp now = null;
|
|
||||||
|
|
||||||
while (notInterrupted) {
|
|
||||||
CALENDAR.setTimeInMillis(System.currentTimeMillis());
|
|
||||||
try {
|
|
||||||
wait((retry ? 1:58-CALENDAR.get(Calendar.MINUTE)) * MINUTES_TO_MILLISEC);
|
|
||||||
CALENDAR.setTimeInMillis(System.currentTimeMillis());
|
|
||||||
if (retry == false) {
|
|
||||||
now = new Timestamp(CALENDAR.getTimeInMillis());
|
|
||||||
heartRate = fitbit.getHeartRate(60);
|
|
||||||
}
|
|
||||||
|
|
||||||
conn.createStatement().execute("INSERT INTO heart (day_hour, rate) VALUES ( ' " + now + " ', '" + heartRate + "')");
|
|
||||||
LOG.info(CALENDAR.getTime() + " > Ho inserito i dati orari "+now);
|
|
||||||
retry = false;
|
|
||||||
wait(MINUTES_TO_MILLISEC);
|
|
||||||
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
notInterrupted = false;
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOG.error(CALENDAR.getTime() + " " + e.getLocalizedMessage() + " > Non e' stato possibile aggingere i dati orari al database, riprovo fra un minuto "+now);
|
|
||||||
retry = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prendi il Runnable che automaticamente gestisce l'inserimento dei dati giornalieri<br>
|
|
||||||
* <br>
|
|
||||||
* Il runnable e' synchronized (si spera thread safe)
|
|
||||||
* @param fitbit la classe che contiene i dati aggiornati
|
|
||||||
* @return un Runnable
|
|
||||||
*/
|
|
||||||
public Runnable insertDailyData(Fitbit fitbit) {
|
|
||||||
return new Runnable() {
|
|
||||||
@Override
|
|
||||||
public synchronized void run() {
|
|
||||||
boolean notInterrupted = true;
|
|
||||||
boolean retry = false;
|
|
||||||
double heartRate = 0;
|
|
||||||
long sleepTime = 0;
|
|
||||||
long steps = 0;
|
|
||||||
List<Sleep.SleepData> sleepDatas = null;
|
|
||||||
Timestamp now = null;
|
|
||||||
|
|
||||||
while (notInterrupted) {
|
|
||||||
CALENDAR.setTimeInMillis(System.currentTimeMillis());
|
|
||||||
try {
|
|
||||||
wait((retry? 1:(22-CALENDAR.get(Calendar.HOUR))*60) * MINUTES_TO_MILLISEC);
|
|
||||||
CALENDAR.setTimeInMillis(System.currentTimeMillis());
|
|
||||||
if (retry == false) {
|
|
||||||
heartRate = fitbit.getHeartRate(60 * 24);
|
|
||||||
sleepTime = fitbit.getHoursSleep();
|
|
||||||
sleepDatas = fitbit.getDetailedSleep();
|
|
||||||
steps = fitbit.getSteps();
|
|
||||||
now = new Timestamp(CALENDAR.getTimeInMillis());
|
|
||||||
}
|
|
||||||
|
|
||||||
conn.createStatement().execute("INSERT INTO total (day, sleep_time, heart_rate, steps) VALUES ( '" + now + "', '" + sleepTime + "', '" + heartRate + "', '" + steps + "' )");
|
|
||||||
for (Sleep.SleepData data : sleepDatas)
|
|
||||||
conn.createStatement().execute("INSERT INTO total (sleep_start, sleep_end, duration) VALUES ( '" + data.start_date + "', '" + data.end_date + "', '" + data.duration + "' )");
|
|
||||||
LOG.info(CALENDAR.getTime() + " > Ho inserito i dati giornalieri");
|
|
||||||
retry = false;
|
|
||||||
wait(MINUTES_TO_MILLISEC);
|
|
||||||
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
notInterrupted = false;
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOG.error(CALENDAR.getTime() + " " + e.getLocalizedMessage() + " > Non e' stato possibile aggingere i dati della giornata al database, riprovo fra un minuto");
|
|
||||||
retry = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
public ResultSet getDataFromDatabase(String sql) throws SQLException {
|
|
||||||
Statement statement = conn.createStatement();
|
|
||||||
ResultSet rs = statement.executeQuery(sql);
|
|
||||||
return rs;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -83,7 +83,6 @@ public class Rest {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
LOG.error("PUT: " + e.getMessage());
|
LOG.error("PUT: " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
156
src/main/java/support/database/Database.java
Normal file
156
src/main/java/support/database/Database.java
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
package support.database;
|
||||||
|
|
||||||
|
import device.Fitbit;
|
||||||
|
import device.fitbitdata.HeartRate;
|
||||||
|
import device.fitbitdata.Sleep;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface Database {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Un logger per scrivere a console eventuali errori o informazioni
|
||||||
|
*/
|
||||||
|
Logger LOG = LoggerFactory.getLogger("DB");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Una costante che indica quanti millisecondi ci sono in un minuto (utile per le conversioni)
|
||||||
|
*/
|
||||||
|
int MILLISEC_IN_MINUTE = 60000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dice solamente se e' possibile collegarsi al database e se si possono fare delle query
|
||||||
|
* @return vero se si pu' falso in altri casi.
|
||||||
|
*/
|
||||||
|
boolean isReachable();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserisce nuovi dati del paziente nel database.
|
||||||
|
* @param dateMilliSec la data che si vuole inserire in millisec
|
||||||
|
* @param heartRate il battito cardiaco
|
||||||
|
* @return vero se ha inserito o i dati esistevano gia' falso se non ce l'ha fatta
|
||||||
|
*/
|
||||||
|
boolean updateHeart(long dateMilliSec, double heartRate);
|
||||||
|
/**
|
||||||
|
* Inserisce nuovi dati del paziente nel database.
|
||||||
|
* @param dateStartSleep la data che si vuole inserire in millisec
|
||||||
|
* @param duration per quanto e' durato il sonno
|
||||||
|
* @return vero se ha inserito o i dati esistevano gia' falso se non ce l'ha fatta
|
||||||
|
*/
|
||||||
|
boolean updateSleep(long dateStartSleep, long duration);
|
||||||
|
/**
|
||||||
|
* Inserisce nuovi dati del paziente nel database.
|
||||||
|
* @param dateMilliSec la data che si vuole inserire in millisec
|
||||||
|
* @param steps i passi fatti
|
||||||
|
* @return vero se ha inserito o i dati esistevano gia' falso se non ce l'ha fatta
|
||||||
|
*/
|
||||||
|
boolean updateSteps(long dateMilliSec, long steps);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Riceve i dati del cuore dal giorno selezionato fino ad oggi
|
||||||
|
* @param days quanti giorni devono esser considerati
|
||||||
|
* @return una lista dei battiti cardiaci degli ultimi X giorni (ordinati da oggi al giorno X)
|
||||||
|
*/
|
||||||
|
List<HeartRate> getHeartDataOfLast(int days);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prendi il Thread che automaticamente gestisce l'inserimento dei dati orari (per ora solo il battito cardiaco)<br>
|
||||||
|
* Se per caso c'e' un fallimento riprova ad inserire i dati ogni x minuti, indicati dal terzo parametro<br>
|
||||||
|
* @param database il database in cui inserirlo
|
||||||
|
* @param fitbit la classe che contiene i dati aggiornati
|
||||||
|
* @param retryMinutes ogni quanti minuti deve riprovare ad inviare la richiesta
|
||||||
|
* @return un Thread
|
||||||
|
*/
|
||||||
|
static Thread insertHourlyDataIn(Database database, Fitbit fitbit, int retryMinutes) {
|
||||||
|
Runnable runnable = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public synchronized void run() {
|
||||||
|
LOG.info("Aggiornamento orario iniziato");
|
||||||
|
try {
|
||||||
|
boolean retry;
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
double heartRate = 30;//fitbit.getHeartRate(60);
|
||||||
|
do {
|
||||||
|
retry = !database.updateHeart(now, heartRate);
|
||||||
|
LOG.info("Aggiornamento " + (!retry ? "riuscito" : "fallito, riprovo fra " + retryMinutes + " minuti"));
|
||||||
|
if (retry)
|
||||||
|
wait(retryMinutes * MILLISEC_IN_MINUTE);
|
||||||
|
} while(retry);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.warn("Aggiornamento interrotto");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return getThreadStartingEach(runnable, "update-hourly-data", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prendi il Thread che automaticamente gestisce l'inserimento dei dati giornalieri<br>
|
||||||
|
* Se per caso c'e' un fallimento riprova ad inserire i dati ogni x minuti, indicati dal terzo parametro<br>
|
||||||
|
* @param database il database in cui inserirlo
|
||||||
|
* @param fitbit la classe che contiene i dati aggiornati
|
||||||
|
* @param retryMinutes ogni quanti minuti deve riprovare ad inviare la richiesta
|
||||||
|
* @return un Thread da far partire
|
||||||
|
*/
|
||||||
|
static Thread insertDailyData(Database database, Fitbit fitbit, int retryMinutes) {
|
||||||
|
Runnable runnable = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public synchronized void run() {
|
||||||
|
LOG.info("Aggiornamento giornaliero iniziato");
|
||||||
|
try {
|
||||||
|
boolean retry;
|
||||||
|
long steps = fitbit.getSteps();
|
||||||
|
List<Sleep.SleepData> sleepDatas = fitbit.getDetailedSleep();
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
do {
|
||||||
|
retry = !database.updateSteps(now, steps);
|
||||||
|
for (Sleep.SleepData data : sleepDatas)
|
||||||
|
retry = retry && !database.updateSleep(data.start_date, data.duration);
|
||||||
|
|
||||||
|
LOG.info("Aggiornamento " + (!retry ? "riuscito" : "fallito, riprovo fra " + retryMinutes + " minuti"));
|
||||||
|
if (retry)
|
||||||
|
wait(retryMinutes * MILLISEC_IN_MINUTE);
|
||||||
|
} while (retry);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOG.warn("Aggiornamento interrotto");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return getThreadStartingEach(runnable, "update-daily-data", 24*60);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restuisce un thread che se fatto partire, esegue il runnable in un sub-thread ogni X minuti<br>
|
||||||
|
* Il sotto thread lanciato avra' lo stesso nome, ma con un trattino e la data di lancio a seguito<br>
|
||||||
|
* Se il thread viene interrotto non fa piu' partire il runnable e si ferma
|
||||||
|
* @param runnable il runnable da lanciare
|
||||||
|
* @param threadName il nome da dare al thread
|
||||||
|
* @param minutes i minuti da aspettare, se negativi o 0 ritorna null
|
||||||
|
*/
|
||||||
|
static Thread getThreadStartingEach(final Runnable runnable, String threadName, int minutes) {
|
||||||
|
if(minutes<1)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public synchronized void run() {
|
||||||
|
boolean notInterrupted = true;
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
wait(minutes * MILLISEC_IN_MINUTE);
|
||||||
|
Thread thread = new Thread(runnable, threadName + "-" + new Timestamp(System.currentTimeMillis()));
|
||||||
|
thread.start();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
notInterrupted = false;
|
||||||
|
}
|
||||||
|
} while (notInterrupted);
|
||||||
|
}
|
||||||
|
}, threadName);
|
||||||
|
}
|
||||||
|
}
|
||||||
106
src/main/java/support/database/LocalDB.java
Normal file
106
src/main/java/support/database/LocalDB.java
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
package support.database;
|
||||||
|
|
||||||
|
import device.fitbitdata.HeartRate;
|
||||||
|
|
||||||
|
import java.sql.*;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classe che utilizza un database sqlite che contiene le seguenti tabelle:<br>
|
||||||
|
* <ul>
|
||||||
|
* <li>'heart' battito + orario</li>
|
||||||
|
* <li>'sleep' inizio + durata</li>
|
||||||
|
* <li>'steps' data + passi.</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public class LocalDB implements Database {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Il percorso di dove trovare il database, strutturato in: <interfaccia>:<implementazione>:<percorso vero e proprio>
|
||||||
|
*/
|
||||||
|
public static final String DB_LOCATION = "jdbc:sqlite:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Il nome del database (aka il nome del file)
|
||||||
|
*/
|
||||||
|
public static final String DB_NAME = "user_data.db";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* La connessione al database
|
||||||
|
*/
|
||||||
|
private final Connection conn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crea una connessione al Database specificato in DB_LOCATION e con il nome DB_NAME.
|
||||||
|
* Se il Database non esiste lo crea e inizializza anche delle tabelle:
|
||||||
|
* <ul>
|
||||||
|
* <li>'heart' battito + orario</li>
|
||||||
|
* <li>'sleep' inizio + durata</li>
|
||||||
|
* <li>'step' data + passi.</li>
|
||||||
|
* </ul>
|
||||||
|
* @throws SQLException se qualcosa e' andato storto
|
||||||
|
*/
|
||||||
|
public LocalDB() throws SQLException {
|
||||||
|
conn = DriverManager.getConnection(DB_LOCATION + DB_NAME);
|
||||||
|
Statement statement = conn.createStatement();
|
||||||
|
statement.execute("CREATE TABLE IF NOT EXISTS heart (day DATE PRIMARY KEY, rate DOUBLE)");
|
||||||
|
statement.execute("CREATE TABLE IF NOT EXISTS sleep (sleep_start DATE PRIMARY KEY, duration INTEGER)");
|
||||||
|
statement.execute("CREATE TABLE IF NOT EXISTS steps (day DATE PRIMARY KEY, steps INTEGER)");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReachable() { return conn!=null; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean updateHeart(long dateMilliSec, double heartRate) {
|
||||||
|
return query("INSERT INTO heart (day, rate) VALUES ( ' " + new Timestamp(dateMilliSec) + " ', '" + heartRate + "')");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean updateSleep(long dateStartSleep, long duration) {
|
||||||
|
return query("INSERT INTO sleep (sleep_start, duration) VALUES ( ' " + new Timestamp(dateStartSleep) + " ', '" + duration + "')");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean updateSteps(long dateMilliSec, long steps) {
|
||||||
|
return query("INSERT INTO steps (day, steps) VALUES ( ' " + new Timestamp(dateMilliSec) + " ', '" + steps + "')");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<HeartRate> getHeartDataOfLast(int days) {
|
||||||
|
try {
|
||||||
|
int dayToSubtract = 15;
|
||||||
|
// Calendar calendar = Calendar.getInstance();
|
||||||
|
// calendar.setTimeInMillis(System.currentTimeMillis());
|
||||||
|
// calendar.add(Calendar.DATE, -dayToSubtract);
|
||||||
|
// long time = calendar.getTimeInMillis();
|
||||||
|
long time = System.currentTimeMillis() - (dayToSubtract * 24 * 60 * 1000); // meno 24 giorni per 60 secondi per 100 millisec
|
||||||
|
|
||||||
|
ResultSet result = conn.createStatement().executeQuery("SELECT * FROM heart WHERE day>='" + new Timestamp(time) + "'");
|
||||||
|
List<HeartRate> list = new LinkedList<>();
|
||||||
|
|
||||||
|
while(result.next()) {
|
||||||
|
HeartRate rate = new HeartRate();
|
||||||
|
rate.setAverage(result.getDouble("rate"));
|
||||||
|
rate.setDate(result.getDate("day").getTime());
|
||||||
|
|
||||||
|
list.add(rate);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean query(String sql) {
|
||||||
|
try {
|
||||||
|
conn.createStatement().execute(sql);
|
||||||
|
return true;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
LOG.error(e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
src/main/java/support/database/RemoteDB.java
Normal file
39
src/main/java/support/database/RemoteDB.java
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package support.database;
|
||||||
|
|
||||||
|
import device.fitbitdata.HeartRate;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
// TODO implement
|
||||||
|
public class RemoteDB implements Database {
|
||||||
|
|
||||||
|
public RemoteDB(String url) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReachable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean updateHeart(long dateMilliSec, double heartRate) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean updateSleep(long dateStartSleep, long duration) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean updateSteps(long dateMilliSec, long steps) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<HeartRate> getHeartDataOfLast(int days) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user