diff --git a/src/main/java/device/Sensor.java b/src/main/java/device/Sensor.java index fea305f..e78b257 100644 --- a/src/main/java/device/Sensor.java +++ b/src/main/java/device/Sensor.java @@ -6,7 +6,7 @@ import de.fh_zwickau.informatik.sensor.model.devices.Device; import de.fh_zwickau.informatik.sensor.model.devices.DeviceList; import support.ZWaySimpleCallback; -// TODO da mettere a posto secondo me, dato che da un po di problemi IRL +// TODO GIOVEDI da mettere a posto secondo me, dato che da un po di problemi IRL /** * Sensore che permette di registrare vari dati dell'ambiente */ diff --git a/src/main/java/main/SeniorAssistant.java b/src/main/java/main/SeniorAssistant.java index 8f784ab..d08972e 100644 --- a/src/main/java/main/SeniorAssistant.java +++ b/src/main/java/main/SeniorAssistant.java @@ -47,14 +47,14 @@ public class SeniorAssistant { // list of arguments to use in the classes String hueAddress = arguments.get("hueaddress"); String hueUser = arguments.get("hueuser"); - //TODO String sensorAddress = arguments.get("sensorAddress"); + //TODO GIOVEDI String sensorAddress = arguments.get("sensorAddress"); Integer sensorNode = getInt(arguments.get("sensornode")); String remoteDbUser = arguments.get("remotedbuser"); boolean autoBrightness = arguments.containsKey("autobrightness"); try { LOG.info("Connessione alle Philips Hue..."); - Hue lights = new Hue(hueAddress, hueUser); + Hue lights = (hueAddress!=null && hueUser!=null? new Hue(hueAddress, hueUser):new Hue()); if(autoBrightness) try { LOG.info("Connessione ai sensori..."); @@ -100,16 +100,8 @@ public class SeniorAssistant { /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 musica tramite comando vocale - TODO la musica non funzia su linux, ma forse - provando ad installare tramite comando: sudo apt-get install ia32-libs-gtk - oppure con: sudo apt-get install libgtk-3-dev - oppure con: sudo apt-get install libgnomeui-dev libxtst-dev freeglut3-dev libgtk-3-dev libgtk2.0-dev + XXX Gestione musica tramite comando vocale //TODO mettere a posto dialogflow e inserire qualche canzone - guardare qui: http://www.eclipse.org/swt/faq.php#gtkstartup - - - // Randomly at night heavy metal start */ /* ------------------------------------------------------------------------------------ @@ -117,20 +109,21 @@ public class SeniorAssistant { ------------------------------------------------------------------------------------ */ /** - * Prende gli argomenti nel formato "-(.+)::(.+)" e li inserisce in una mappa. + * Prende gli argomenti nel formato "^-(?<name>[a-zA-Z]+)(::)?(?<argument>.*)$" e li inserisce in una mappa. * Se l'argomento non e' nel formato giusto lo ignora. * @param args un'array di stringhe contente i vari argomenti * @return una mappa con key il nome dell'argomento (la parte prima del :: e dopo il meno) e come valore il valore di esso (la parte dopo ::) */ private static Map getArgsMap(String[] args) { Map map = new HashMap<>(); - Pattern pattern = Pattern.compile("-(.+)::(.+)"); + Pattern pattern = Pattern.compile("^-(?[a-zA-Z]+)(::)?(?.*)$"); for (String arg: args) { Matcher matcher = pattern.matcher(arg); if (matcher.find()) - map.put(matcher.group(1).toLowerCase(), matcher.group(2)); + map.put(matcher.group("name").toLowerCase(), matcher.group("argument")); } + LOG.info(map.toString()); return map; } diff --git a/src/main/java/main/VariousThreads.java b/src/main/java/main/VariousThreads.java index 1ff7c90..90c2d90 100644 --- a/src/main/java/main/VariousThreads.java +++ b/src/main/java/main/VariousThreads.java @@ -5,7 +5,9 @@ import device.Fitbit; import device.Hue; import device.Sensor; import device.fitbitdata.HeartRate; -import support.Musich; +import support.audio.Audio; +import support.audio.AudioFile; +import support.audio.Musich; import support.database.Database; import java.sql.Timestamp; @@ -33,13 +35,14 @@ public class VariousThreads { /** * La variabile per far partire della musica da Youtube */ - private final Musich musich; + private final Audio audio; /** * Costruttore */ public VariousThreads() { - musich = new Musich(); + // audio = new AudioFile(); + audio = System.getProperty("os.name").startsWith("Windows")? new Musich():new AudioFile(); } // TODO aggingere il fitbit per la richiesta dei dati @@ -79,10 +82,10 @@ public class VariousThreads { return null; }); df.addOnAction("SetMusic", (param) -> { - musich.playRandom(param.get("musicType").getAsString(),10); + audio.playRandom(param.get("musicType").getAsString()); return null; }); - df.addOnAction("StopMusic", (params) -> { musich.stop(); return null; }); + df.addOnAction("StopMusic", (params) -> { audio.stop(); return null; }); //TODO aggiungere una azione che faccia in modo di richiedere dei dati in particolare //TODO aggiungere una azione su DialogFlow che riconosca di impostare una playlist (Rilassante, Antica...) diff --git a/src/main/java/support/Rest.java b/src/main/java/support/Rest.java index 03df33b..16bd812 100644 --- a/src/main/java/support/Rest.java +++ b/src/main/java/support/Rest.java @@ -1,6 +1,7 @@ package support; import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; import org.apache.http.HttpResponse; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; @@ -13,6 +14,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -37,21 +39,26 @@ public class Rest { * @return the response, parsed from JSON */ public static Map get(String URL) { - Map response = new HashMap<>(); + Map response = new HashMap<>(); + String json = ""; try { CloseableHttpClient httpclient = HttpClients.createDefault(); HttpGet request = new HttpGet(URL); CloseableHttpResponse result = httpclient.execute(request); - String json = EntityUtils.toString(result.getEntity()); + json = EntityUtils.toString(result.getEntity()); + + try { + response = gson.fromJson(json, Map.class); + } catch (JsonSyntaxException e) { + response.put("list", gson.fromJson(json, List.class)); + } - response = gson.fromJson(json, Map.class); result.close(); - httpclient.close(); LOG.debug("GET response: " + json); } catch (Exception e) { - LOG.error("GET: " + e.getMessage()); + LOG.error("GET: " + URL + " " + e.getMessage() + " " + json); } @@ -75,8 +82,10 @@ public class Rest { request.setEntity(params); HttpResponse result = httpclient.execute(request); - + String json = EntityUtils.toString(result.getEntity()); httpclient.close(); + + LOG.debug("PUT response: " + json); } catch (Exception e) { LOG.error("PUT: " + e.getMessage()); } diff --git a/src/main/java/support/audio/Audio.java b/src/main/java/support/audio/Audio.java new file mode 100644 index 0000000..9d11a3d --- /dev/null +++ b/src/main/java/support/audio/Audio.java @@ -0,0 +1,28 @@ +package support.audio; + +/** + * Classe che serve ad aiutare a far partire la musica + */ +public interface Audio { + + /** + * Fa partire una audio in base al nome di essa.
+ * Se un audio era gia' stato fatto partire esso viene fermato
+ * Il nome puo' variare in base all'implementazione: nome di file o nome da cercare su internet... + * @param name la stringa per far partire la canzone + */ + void play(String name); + + /** + * Fa' partire un audio a caso fra quelli selezionati dalla stringa
+ * Se un audio era gia' stato fatto partire esso viene fermato
+ * In base all'implementazione puo' essere un nome che appartiene a vari file,
+ * il nome di una cartella contenente i file, o una stringa di ricerca... + */ + void playRandom(String name); + + /** + * Ferma l'ultimo che e' stato fatto partire + */ + void stop(); +} diff --git a/src/main/java/support/audio/AudioFile.java b/src/main/java/support/audio/AudioFile.java new file mode 100644 index 0000000..706f4a7 --- /dev/null +++ b/src/main/java/support/audio/AudioFile.java @@ -0,0 +1,118 @@ +package support.audio; + +import sun.audio.AudioPlayer; +import sun.audio.AudioStream; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +/** + * Usa i file nella cartella resources/audio/ per riprodurre i suoni + */ +public class AudioFile implements Audio { + + /** + * La path dove si trovano gli audio + */ + public static final String PATH_AUDIO = "src/main/resources/audio/"; + + /** + * L'ultimo audio fatto partire + */ + private AudioStream lastIn = null; + + /** + * Serve per crearsi una mapp di tutte le canzoni + */ + private Map files = getAllFiles(PATH_AUDIO); + + /** + * Mappa che serve ad avere per ogni sotto-dir di audio una lista di ogni file audio che c'e' + */ + private Map> dirs = getAllDirs(PATH_AUDIO); + + /** + * Fa partire una canzone che si trova nella cartella audio o in una delle sue sottocartelle + * @param name la stringa per far partire la canzone + */ + @Override + public void play(String name) { + stop(); + try { + File file = files.get(name); + lastIn = new AudioStream( new FileInputStream(file)); + AudioPlayer.player.start(lastIn); + + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Fa' partire una canzone a caso nella cartella selezionata + * @param name il nome della cartella + */ + @Override + public void playRandom(String name) { + List songs = dirs.get(name); + play(songs.get((int)(Math.random()*songs.size())).getName()); + } + + @Override + public void stop() { + try { + AudioPlayer.player.stop(lastIn); + lastIn.close(); + lastIn = null; + } catch (IOException e) { + e.printStackTrace(); + } catch (NullPointerException e) {} + } + + /** + * Fa in modo di mappare tutti i file in una directory e in tutte le sue sub-dir + * @param path la path iniziale + * @return una mappa di NomeFile -> File + */ + private Map getAllFiles(String path) { + File folder = new File(path); + File[] listOfFiles = folder.listFiles(); + Map map = new HashMap<>(); + + for (File file : listOfFiles) { + if(file.isFile()) + map.put(file.getName(), file); + else + map.putAll(getAllFiles(file.getPath())); + } + + return map; + } + + /** + * Crea una mappa contenente tutti i file della cartella scelta associati con ogni dir corrente
+ * @param path la path iniziale + * @return una mappa di directory con i loro file + */ + private Map> getAllDirs(String path) { + File folder = new File(path); + File[] listOfFiles = folder.listFiles(); + List list = new LinkedList<>(); + Map> map = new HashMap<>(); + + for (File file : listOfFiles) { + if(file.isFile()) + list.add(file); + else + map.putAll(getAllDirs(file.getPath())); + } + map.put(folder.getName(), list); + + return map; + } +} diff --git a/src/main/java/support/Musich.java b/src/main/java/support/audio/Musich.java similarity index 92% rename from src/main/java/support/Musich.java rename to src/main/java/support/audio/Musich.java index 937f525..bde1791 100644 --- a/src/main/java/support/Musich.java +++ b/src/main/java/support/audio/Musich.java @@ -1,7 +1,8 @@ -package support; +package support.audio; import chrriis.dj.nativeswing.swtimpl.NativeInterface; import chrriis.dj.nativeswing.swtimpl.components.JWebBrowser; +import support.Rest; import javax.swing.*; import java.awt.*; @@ -15,7 +16,7 @@ import java.util.Map; /** * Classe che serve a far partire un video di youtube in una frame */ -public class Musich { +public class Musich implements Audio { /** * L'url da dove possiamo pescare i dati di youtube dei video @@ -142,6 +143,17 @@ public class Musich { this.play(getVideosId(search, maxResult).get((int)(Math.random()*maxResult))); } + /** + * Serve a far partire un video a caso tra quelli che corrispondono alle keyword indicate nella ricerca
+ * Esso scegliera' fra i primi 5 risultati
+ * Come al solito, youtube potrebbe far partire una pubblicita'... eh beh. + * @param search la ricerca da fare su youtube + */ + public void playRandom(String search) { + this.playRandom(search, 5); + } + + /** * Ferma il video che e' in riprduzione in questo momento.
* Se non ce ne sono, amen... non fa nulla. diff --git a/src/main/java/support/database/RemoteDB.java b/src/main/java/support/database/RemoteDB.java index 3477832..bed4b4e 100644 --- a/src/main/java/support/database/RemoteDB.java +++ b/src/main/java/support/database/RemoteDB.java @@ -1,21 +1,50 @@ package support.database; +import ai.api.GsonFactory; +import com.google.gson.Gson; import device.fitbitdata.HeartRate; import support.Rest; -import java.util.List; -import java.util.Map; +import java.sql.Timestamp; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; -// TODO implement +/** + * Classe che si connette al server del progetto di C# + */ public class RemoteDB implements Database { - private final String base_url; - private final String username; + /** + * Serve per mandare i messaggi, convertendo le classi in Json + */ + private static final Gson GSON = GsonFactory.getDefaultFactory().getGson(); + private static final DateFormat STD_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH"); + + /** + * L'url base che verra' usato per inviare/ricevere i dati + */ + public final String base_url; + /** + * L'username del nostro vecchio + */ + public final String username; + + /** + * Inseredolo username e basta l'indirizzo a cui tentera' la connesione e' http://127.0.0.1:5000/api/ + * @param username il nome utente assiociato per aggiornare i dati + */ public RemoteDB(String username) { - this(username, "http://127.0.0.1:5001/api/"); + this(username, "http://127.0.0.1:5000/api/"); } + /** + * Costruttore che ha bisogno sia delo username che del url dper la connesione + * @param username il nome utente assiociato per aggiornare i dati + * @param base_url l'url a cui si punta per aggiornare/leggere i dati + */ public RemoteDB(String username, String base_url) { this.username = username; this.base_url = base_url; @@ -23,29 +52,76 @@ public class RemoteDB implements Database { @Override public boolean isReachable() { - Map map = Rest.get(base_url+"user/"); - LOG.info(map.toString()); - return !map.isEmpty(); + return !Rest.get(base_url+"user/"+username).isEmpty(); } @Override public boolean updateHeart(long dateMilliSec, double heartRate) { - return false; + return sendData("heartbeat", dateMilliSec, heartRate); } @Override public boolean updateSleep(long dateStartSleep, long duration) { - return false; + return sendData("sleep", dateStartSleep, duration); } @Override public boolean updateSteps(long dateMilliSec, long steps) { - return false; + return sendData("step", dateMilliSec, steps); } @Override public List getHeartDataOfLast(int days) { - return null; + try { + Calendar ago = Calendar.getInstance(); + ago.setTimeInMillis(System.currentTimeMillis()); + ago.add(Calendar.DATE, -days); + + DateFormat format = new SimpleDateFormat("yyyy-MM-dd"); + + String url = base_url+"heartbeat/"+username+"/"+format.format(ago.getTime())+"/today/"; + Map>> map = (Map>>) Rest.get(url); + + List list = new ArrayList<>(map.get("list").size()); + for(Map data: map.get("list")) { + HeartRate heart = new HeartRate(); + heart.setAverage((double)data.get("value")); + heart.setDate(STD_FORMAT.parse((String)data.get("time")).getTime()); + + list.add(heart); + } + return list; + } catch (ParseException e) { + LOG.error(e.getMessage()); + return null; + } + } + + /** + * Serve ad inviare una richiesta PUT per aggiornare i dati + * @param type il tipo di dato che deve esser aggiornato + * @param date la data da inserire in millisecondi + * @param value l'oggetto da inviare + * @return vero se dopo la PUT si e' riusciti ad inserire il valore + */ + private boolean sendData(String type, long date, Object value) { + String url = base_url+type+"/"; + Map map = new HashMap<>(); + map.put("username", username); + map.put("time", new Timestamp(date)); + map.put("value", value); + + Rest.put(url, GSON.toJson(map), "application/json"); + DateFormat format = new SimpleDateFormat("yyyy-MM-dd/HH"); + + url = url+username+"/"+format.format(new Date(date)); + List> list = (List>) Rest.get(url).get("list"); + for(Map obj: list) + try { + if (STD_FORMAT.parse((String) obj.get("time")).getTime() == date) + return true; + } catch (Exception e) {} + return false; } } diff --git a/src/main/resources/audio/random/Godzilla.wav b/src/main/resources/audio/random/Godzilla.wav new file mode 100644 index 0000000..4831bab Binary files /dev/null and b/src/main/resources/audio/random/Godzilla.wav differ diff --git a/src/main/resources/audio/random/LeeroyJenkins.wav b/src/main/resources/audio/random/LeeroyJenkins.wav new file mode 100644 index 0000000..1b23254 Binary files /dev/null and b/src/main/resources/audio/random/LeeroyJenkins.wav differ diff --git a/src/main/resources/audio/random/Tullio.wav b/src/main/resources/audio/random/Tullio.wav new file mode 100644 index 0000000..f96baf9 Binary files /dev/null and b/src/main/resources/audio/random/Tullio.wav differ diff --git a/src/test/java/test/TestMusich.java b/src/test/java/test/TestMusich.java index 80ba880..df898cf 100644 --- a/src/test/java/test/TestMusich.java +++ b/src/test/java/test/TestMusich.java @@ -1,7 +1,8 @@ package test; import org.junit.Test; -import support.Musich; +import support.audio.AudioFile; +import support.audio.Musich; public class TestMusich { @@ -17,6 +18,22 @@ public class TestMusich { musich.stop(); } + @Test + public void test2() { + AudioFile audio = new AudioFile(); + audio.play("Godzilla.wav"); // apparently it doesn't like some wav + waitAndPrint(3); + audio.play("Tullio.wav"); + waitAndPrint(10); + audio.stop(); + waitAndPrint(2); + audio.play("LeeroyJenkins.wav"); + waitAndPrint(5); + audio.playRandom("random"); + waitAndPrint(10); + audio.stop(); + } + public void waitAndPrint(Integer seconds) { if(seconds != null) synchronized (seconds) { try { diff --git a/src/test/java/test/TestRemoteDB.java b/src/test/java/test/TestRemoteDB.java index 4457bea..00a60ae 100644 --- a/src/test/java/test/TestRemoteDB.java +++ b/src/test/java/test/TestRemoteDB.java @@ -8,12 +8,17 @@ import static org.junit.Assert.assertTrue; public class TestRemoteDB { - private static final String REMOTE_URL = "http://127.0.0.1:5001/api/"; - private static final String USERNAME = "vecchio"; + private static final String REMOTE_URL = "http://127.0.0.1:5000/api/"; + private static final String USERNAME = "vecchio1"; @Test public void test() { Database database = new RemoteDB(USERNAME, REMOTE_URL); assertTrue(database.isReachable()); + + //assertTrue(database.updateHeart(System.currentTimeMillis(), Math.random()*70 + 50)); + //assertTrue(database.updateSleep(System.currentTimeMillis(), (long) (Math.random()*7200000) + 0)); + //assertTrue(database.updateSteps(System.currentTimeMillis(), (long) (Math.random()*100) + 100)); + //database.getHeartDataOfLast(10); } }