From 7b21345f89e772360eb26801e202c13eaf3d1a7d Mon Sep 17 00:00:00 2001 From: Giacomo Date: Wed, 29 Aug 2018 00:52:40 +0200 Subject: [PATCH] Builded WebHook for DialogFlow --- README.md | 5 +- SeniorAssistant.iml | 1 + build.gradle | 24 +++-- src/main/java/device/DialogFlow.java | 9 -- src/main/java/device/DialogFlowWebHook.java | 109 ++++++++++++++++++++ src/main/java/device/Sensor.java | 62 ++++++++--- src/main/java/main/Main.java | 36 ++++++- src/main/java/support/DBConnect.java | 39 +++++++ src/test/java/test/TestDialogFlow.java | 18 ++++ src/test/java/{ => test}/TestFitbit.java | 35 ++++--- src/test/java/{ => test}/TestLights.java | 2 + src/test/java/{ => test}/TestSensor.java | 2 + 12 files changed, 285 insertions(+), 57 deletions(-) delete mode 100644 src/main/java/device/DialogFlow.java create mode 100644 src/main/java/device/DialogFlowWebHook.java create mode 100644 src/main/java/support/DBConnect.java create mode 100644 src/test/java/test/TestDialogFlow.java rename src/test/java/{ => test}/TestFitbit.java (96%) rename src/test/java/{ => test}/TestLights.java (98%) rename src/test/java/{ => test}/TestSensor.java (98%) diff --git a/README.md b/README.md index 541cd7f..90e67d8 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,8 @@ Il nostro progetto nasce per aiutare nella quotidianità persone anziane che non possono essere seguite da assistenti e che quindi possono trarre vantaggio da un sistema automatizzato che interagisca attraverso un assistente vocale in modo da permettere al soggetto di controllare i dispositivi collegati alla Home Station. In caso di stress (rilevato attraverso battito cardiaco), le luci vengono soffuse così da creare un ambiente più rilassante e nel caso in cui la situazione non migliori contatti medico o familiari; inoltre viene consigliata in questo caso musica rilassante che il soggetto può avviare con comando vocale. Inoltre il soggetto viene sollecitato vocalmente in caso di sedentarietà. Si mantiene anche il contatto con persone esterne, medico e familiari, i quali possono controllare le attività del soggetto poiché verranno mantenute statistiche su di esse. # TODO -- Aggiungere url generato da ngrok sul Webhook di DialogFlow -- Implementare la funzione getCurrentBrightness() nella classe Hue -- Documentazione per capire meglio (Sensor per esempio manca) +- Documentazione per capire meglio +- Main da iniziare e finire [Jack]: diff --git a/SeniorAssistant.iml b/SeniorAssistant.iml index 405022e..cc64ecb 100644 --- a/SeniorAssistant.iml +++ b/SeniorAssistant.iml @@ -12,6 +12,7 @@ + diff --git a/build.gradle b/build.gradle index 3ddc714..1214e34 100644 --- a/build.gradle +++ b/build.gradle @@ -15,9 +15,9 @@ repositories { dependencies { testCompile group: 'junit', name: 'junit', version: '4.12' -// compile "com.sparkjava:spark-core:2.5.5" - compile "com.google.code.gson:gson:2.8.0" -// compile "org.xerial:sqlite-jdbc:3.15.1" + compile "com.sparkjava:spark-core:2.7.2" + compile "com.google.code.gson:gson:2.8.4" +// compile "org.xerial:sqlite-jdbc:3.21.0.1" //todo remove commenting because "You need to install an appropriate JDBC (Java Database Connectivity) driver to run your Java database programs." compile 'org.apache.httpcomponents:httpclient:4.5.3' compile 'com.google.api-client:google-api-client:1.23.0' compile group: 'com.google.oauth-client', name: 'google-oauth-client-jetty', version: '1.11.0-beta' @@ -27,18 +27,20 @@ dependencies { compile files('lib/zway-lib-0.2.9-SNAPSHOT.jar') compile 'org.apache.commons:commons-lang3:3.4' - compile 'org.eclipse.jetty:jetty-client:9.3.11.v20160721' - compile 'org.eclipse.jetty:jetty-http:9.3.11.v20160721' - compile 'org.eclipse.jetty:jetty-io:9.3.11.v20160721' - compile 'org.eclipse.jetty:jetty-util:9.3.11.v20160721' - compile 'org.eclipse.jetty.websocket:websocket-api:9.3.12.v20160915' - compile 'org.eclipse.jetty.websocket:websocket-client:9.3.12.v20160915' - compile 'org.eclipse.jetty.websocket:websocket-common:9.3.12.v20160915' + compile 'org.eclipse.jetty:jetty-client:9.4.11.v20180605' + compile 'org.eclipse.jetty:jetty-http:9.4.11.v20180605' + compile 'org.eclipse.jetty:jetty-io:9.4.11.v20180605' + compile 'org.eclipse.jetty:jetty-util:9.4.11.v20180605' + compile 'org.eclipse.jetty.websocket:websocket-api:9.4.11.v20180605' + compile 'org.eclipse.jetty.websocket:websocket-client:9.4.11.v20180605' + compile 'org.eclipse.jetty.websocket:websocket-common:9.4.11.v20180605' compile 'org.slf4j:slf4j-simple:1.7.21' //DialogFlow -// compile "ai.api:libai:1.6.12" + compile "ai.api:libai:1.6.12" +// compile 'com.google.cloud:google-cloud-dialogflow:0.59.0-alpha' // for the v2 of dialogflow //for objectMapper compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.5' + implementation 'junit:junit:4.12' } diff --git a/src/main/java/device/DialogFlow.java b/src/main/java/device/DialogFlow.java deleted file mode 100644 index c54c817..0000000 --- a/src/main/java/device/DialogFlow.java +++ /dev/null @@ -1,9 +0,0 @@ -package device; - -public class DialogFlow { - - public DialogFlow() { - - } - -} diff --git a/src/main/java/device/DialogFlowWebHook.java b/src/main/java/device/DialogFlowWebHook.java new file mode 100644 index 0000000..8bdc3f9 --- /dev/null +++ b/src/main/java/device/DialogFlowWebHook.java @@ -0,0 +1,109 @@ +package device; + +import ai.api.GsonFactory; +import ai.api.model.AIResponse; +import ai.api.model.Fulfillment; +import com.google.gson.Gson; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +import static spark.Spark.post; + +/** + * Classe per creare un Webhook che Dialog-Flow possa utilizzare per le sue azioni + */ +public class DialogFlowWebHook { + + /** + * Un logger per vedere le cose piu' easy + */ + private final Logger log = LoggerFactory.getLogger(this.getClass()); + + /** + * Errore che viene mostrato all'utente se l'azione inviata non corrisponde a nessuna di quelle inserite + */ + public static final String ERROR = "Non mi hanno imparato abbastanza per fare questo"; + + /** + * L'eventuale path successiva all'url dichiarato nel Webhook di Dialog-Flow + */ + public final String path; + + /** + * Mappa che contiene tutte le azioni e il loro ID + */ + private final Map actions; + + /** + * Crea una classe vuota per un server che risponde lle chiamate di Dialog-Flow. + * La path viene impostata di default a "/" + */ + public DialogFlowWebHook() { + this("/"); + } + + /** + * Crea una classe vuota per un server che risponde lle chiamate di Dialog-Flow. + * @param path il percorso dopo l'url inidicato nel WebHook di Dialog-Flow + */ + public DialogFlowWebHook(String path) { + this.path = path; + this.actions = new HashMap<>(); + } + + /** + * Aggiunge un'azione ad una specifica richiesta di Dialog-Flow + * @param actionId il nome dell'azione che viene passata da Dialog-Flow + * @param action l'azione da fare (usare lambda) + */ + public void addOnAction(String actionId, Action action) { + this.actions.put(actionId, action); + } + + /** + * Fa partire il server per accettare richieste da Dialog-Flow. + * Ogni richiesta viene esaminata e fatta coincidere con una azione specificata precedentemente. + * Se nessuna azione viene riscontrata, viene inviato un errore, rimuovendo i messaggi + */ + public void startServer() { // todo add param port? Spark.port(num); + Gson gson = GsonFactory.getDefaultFactory().getGson(); + post(this.path, (request, response) -> { + Fulfillment output = new Fulfillment(); + AIResponse input = gson.fromJson(request.body(), AIResponse.class); + + String text = null; + try { + log.info("AZIONE: "+input.getResult().getAction()); + Action action = actions.get(input.getResult().getAction()); + text = action.doAction(); + } catch (NullPointerException e) { + log.info("NESSUNA AZIONE TROVATA"); + text = ERROR; + } + + if(text != null) { + log.info(text); + output.setDisplayText(text); + output.setSpeech(text); + } + + response.type("application/json"); + return output; + }, gson::toJson); + } + + /** + * Interfaccia usata per fare un'azione per ogni Id di Dialog-Flow + */ + public interface Action { + /** + * Fai l'azione desiderata. + * Se ritorna una stringa allora il testo viene cambiato. Se ritorna null non cambia il testo + * @return Una stringa che verra' usata come messaggio o null se non si vuole + */ + String doAction(); + } +} diff --git a/src/main/java/device/Sensor.java b/src/main/java/device/Sensor.java index f846d47..ba084f4 100644 --- a/src/main/java/device/Sensor.java +++ b/src/main/java/device/Sensor.java @@ -6,28 +6,41 @@ import de.fh_zwickau.informatik.sensor.model.devices.Device; import de.fh_zwickau.informatik.sensor.model.devices.DeviceList; import support.ZWaySimpleCallback; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - /** * Sensore che permette di registrare vari dati dell'ambiente */ public class Sensor { - - /** - * Logger? - */ - Logger logger = LoggerFactory.getLogger(Sensor.class); - // sample RaZberry IP address - public String ipAddress = "172.30.1.137"; + /* todo ma serve il LOGGER? + private Logger logger = LoggerFactory.getLogger(Sensor.class); + */ - // sample username and password - public String username = "admin"; - public String password = "raz4reti2"; + /** + * IP del sensore a cui ci si vuole agganciare + */ + private static final String IP_ADDRESS = "172.30.1.137"; - public IZWayApi zwayApi; + /** + * Porta in cui si ascolta per i sensori + */ + private static final int PORT = 8083; + + /** + * Username con cui si entra nel dispositivo + */ + private static final String USERNAME = "admin"; + /** + * Password del dispositivo + */ + private final String PASSWORD = "raz4reti2"; + + /** + * Tutti i devices che esistono nella rete + */ private DeviceList allZWaveDevices; + /** + * I device che vengono selezionati e filtrati dall'utente (ovvero quelli che verranno usati per prendere i dati) + */ private DeviceList devices; /** @@ -37,9 +50,13 @@ public class Sensor { this(null); } + /** + * Si connette ad un sensore che ha il nodeId selezioniato + * @param nodeId nodo che viene selezionato + */ public Sensor (Integer nodeId) { // create an instance of the Z-Way library; all the params are mandatory (we are not going to use the remote service/id) - zwayApi = new ZWayApiHttp(ipAddress, 8083, "http", username, password, 0, false, new ZWaySimpleCallback()); + IZWayApi zwayApi = new ZWayApiHttp(IP_ADDRESS, PORT, "http", USERNAME, PASSWORD, 0, false, new ZWaySimpleCallback()); // get all the Z-Wave devices allZWaveDevices = zwayApi.getDevices(); @@ -50,6 +67,10 @@ public class Sensor { devices = allZWaveDevices; } + /** + * Cambia i dispositivi selezionati in base al nodeId che viene scelto + * @param nodeId il nodo che viene selezionato + */ public void useNode(int nodeId) { devices = new DeviceList(); for (Device devi : allZWaveDevices.getAllDevices()) @@ -57,6 +78,10 @@ public class Sensor { devices.addDevice(devi); } + /** + * Legge i valori della luminosita' segnata dai dispositivi e ne ritorna il valore + * @return la luminopsita' segnata dai dispositivi + */ public int getBrightnessLevel() { for (Device device : devices.getAllDevices()) if (device.getMetrics().getProbeTitle().equalsIgnoreCase("luminiscence")) @@ -64,8 +89,13 @@ public class Sensor { return -99; } + /** + * 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 + * @throws InterruptedException nel caso che succeda qualcosa + */ synchronized public void update(int timeout) throws InterruptedException { - //setInitialValues(); + wait(timeout); for (Device device : devices.getAllDevices()) device.update(); wait(timeout); diff --git a/src/main/java/main/Main.java b/src/main/java/main/Main.java index ddd3180..7ba363e 100644 --- a/src/main/java/main/Main.java +++ b/src/main/java/main/Main.java @@ -7,6 +7,39 @@ import device.*; */ public class Main { + public static void main(String[] args) { + DialogFlowWebHook df = new DialogFlowWebHook(); + + df.addOnAction("LightsON", () -> {return "Luci accese";}); + df.addOnAction("LightsOFF", () -> {return "Luci spente";}); + + df.startServer(); + } + + /** + * Cose da fare in questa funzione: + * - far partire il database + * - ogni ora aggiornare i dati del cuore. (Runnable che gira da se') + * - alla fine della giornata fare un riepilogo del paziente (Runnable che gira da se') + * (magari ci si calcola quando bisogna risvegliarsi e si mette un wait) + * @param fibit da dove prende i dati + */ + private void startDb(Fitbit fibit) { + /* + try { + Connection conn = DBConnect.getInstance().getConnection(); + PreparedStatement st = conn.prepareStatement(""); + + ResultSet rs = st.executeQuery(); + conn.close(); + + } catch (SQLException e) { + e.printStackTrace(); + } + */ + } + + /* public static void main(String[] args) throws Exception { Fitbit fitbit = new Fitbit(); Sensor sensor = new Sensor(); @@ -17,7 +50,7 @@ public class Main { int brightness = sensor.getBrightnessLevel(); // AUTOMATIC - // Inserire ui dati nel DB ogni ora + // Gestione DB in modo che si aggiorni ogni ora // Gestione luci in modo che la luminosità sia sempre la stessa // Gestione luci a seconda del battito cardiaco // Ad una certa ora guarda i passi e se sono pochi dillo @@ -31,4 +64,5 @@ public class Main { // Randomly at night heavy metal start } } + */ } diff --git a/src/main/java/support/DBConnect.java b/src/main/java/support/DBConnect.java new file mode 100644 index 0000000..94d58dd --- /dev/null +++ b/src/main/java/support/DBConnect.java @@ -0,0 +1,39 @@ +package support; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + +/** + * Handle the connection to the SQLite database that stores our tasks. + * @author Luigi De Russis + * @version 1.1 (06/05/2018) + */ +public class DBConnect { + + // todo add a db where we put daily (or hourly, but only for heart) updates + static private final String DB_LOCATION = "jdbc:sqlite:src/main/resources/tasks.db"; + static private DBConnect instance = null; + + private DBConnect() { + instance = this; + } + + public static DBConnect getInstance() { + return (instance == null ? new DBConnect() : instance); + } + + public Connection getConnection() throws SQLException { + try { + /* todo this might work for create the database + Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/"); + Statement s = Conn.createStatement(); + int result = s.executeUpdate("CREATE DATABASE databasename"); + st.close(); + */ + return DriverManager.getConnection(DB_LOCATION); + } catch (SQLException e) { + throw new SQLException("Cannot get connection to " + DB_LOCATION, e); + } + } +} diff --git a/src/test/java/test/TestDialogFlow.java b/src/test/java/test/TestDialogFlow.java new file mode 100644 index 0000000..b435b21 --- /dev/null +++ b/src/test/java/test/TestDialogFlow.java @@ -0,0 +1,18 @@ +package test; + +import device.DialogFlowWebHook; +import org.junit.Test; + + +public class TestDialogFlow { + + @Test + public void test01() { + DialogFlowWebHook webHook = new DialogFlowWebHook(); + + webHook.addOnAction("LightsON", () -> {return "Luci accese";}); + webHook.addOnAction("LightsOFF", () -> {return "Luci spente";}); + + webHook.startServer(); + } +} diff --git a/src/test/java/TestFitbit.java b/src/test/java/test/TestFitbit.java similarity index 96% rename from src/test/java/TestFitbit.java rename to src/test/java/test/TestFitbit.java index 760c64f..6e3e4fc 100644 --- a/src/test/java/TestFitbit.java +++ b/src/test/java/test/TestFitbit.java @@ -1,17 +1,18 @@ - -import device.Fitbit; -import org.junit.Test; - -public class TestFitbit { - - @Test - public void test01() throws Exception { - Fitbit fitBit = new Fitbit(); - fitBit.getHoursSleep(); - - System.out.println("Today's average heart-rate: "+fitBit.getHeartRate()); - System.out.println("Today's hours of sleep: "+fitBit.getHoursSleep()); - System.out.println("Today's steps: "+fitBit.getSteps()); - System.out.println("Fine."); - } -} +package test; + +import device.Fitbit; +import org.junit.Test; + +public class TestFitbit { + + @Test + public void test01() throws Exception { + Fitbit fitBit = new Fitbit(); + fitBit.getHoursSleep(); + + System.out.println("Today's average heart-rate: "+fitBit.getHeartRate()); + System.out.println("Today's hours of sleep: "+fitBit.getHoursSleep()); + System.out.println("Today's steps: "+fitBit.getSteps()); + System.out.println("Fine."); + } +} diff --git a/src/test/java/TestLights.java b/src/test/java/test/TestLights.java similarity index 98% rename from src/test/java/TestLights.java rename to src/test/java/test/TestLights.java index 1b8fcf3..d21d0a5 100644 --- a/src/test/java/TestLights.java +++ b/src/test/java/test/TestLights.java @@ -1,3 +1,5 @@ +package test; + import device.Hue; import org.junit.Test; diff --git a/src/test/java/TestSensor.java b/src/test/java/test/TestSensor.java similarity index 98% rename from src/test/java/TestSensor.java rename to src/test/java/test/TestSensor.java index c4cd74d..4e60579 100644 --- a/src/test/java/TestSensor.java +++ b/src/test/java/test/TestSensor.java @@ -1,3 +1,5 @@ +package test; + import device.Hue; import device.Sensor; import org.junit.Test;