diff --git a/APED/app/src/main/java/com/example/aped/communication/Communicator.java b/APED/app/src/main/java/com/example/aped/communication/Communicator.java index 3fee86c..f10211d 100644 --- a/APED/app/src/main/java/com/example/aped/communication/Communicator.java +++ b/APED/app/src/main/java/com/example/aped/communication/Communicator.java @@ -2,56 +2,148 @@ package com.example.aped.communication; import android.content.Context; import android.util.Log; + import com.android.volley.Request; import com.android.volley.RequestQueue; import com.android.volley.Response; import com.android.volley.toolbox.JsonObjectRequest; import com.android.volley.toolbox.Volley; +import com.example.aped.utils.ExternalStorageHandler; + import org.json.JSONObject; + import java.io.File; -import kotlin.NotImplementedError; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +/** + * Class that handles communication with the raspberry pi. + */ public class Communicator { - private String address; - private int port; - private RequestQueue requestQueue; - public Communicator(String address, int port, Context context) { - this.address = address; - this.port = port; - requestQueue = Volley.newRequestQueue(context); + /** Ipv4 address of the raspberry. **/ + private final String address; + /** API port of the raspberry. **/ + private final int port; + /** Request queue used for asynchronous requests. **/ + private final RequestQueue requestQueue; + /**The context of the application.**/ + private final Context context; + + /** + * Constructor of the Communicator. + * @param pAddress the ipv4 address of the raspberry + * @param pPort the port of the raspberry + * @param pContext the context of the application + */ + public Communicator(final String pAddress, + final int pPort, + final Context pContext) { + this.address = pAddress; + this.port = pPort; + requestQueue = Volley.newRequestQueue(pContext); + this.context = pContext; } - public void read(String deviceName, Response.Listener responseListener) { - String requestString = "http://" + address + ":" + port + "/device/" + deviceName + "/"; + /** + * Reads the device state from the raspberry. + * @param deviceName the name of the device + * @param responseListener the {@link Response.Listener} for defining + * actions to be performed on response + */ + public void read(final String deviceName, + final Response.Listener responseListener) { + String url = "http://" + address + + ":" + port + + "/device/" + deviceName + "/"; JsonObjectRequest request = new JsonObjectRequest( Request.Method.GET, - requestString, + url, null, responseListener, - error -> Log.e("Communicator", "Error during READ: " + error.getMessage()) + error -> Log.e("Communicator", + "Error during READ: " + error.getMessage()) ); requestQueue.add(request); } - public void write(String deviceName, JSONObject message, Response.Listener responseListener) { - String requestString = "http://" + address + ":" + port + "/device/" + deviceName + "/"; + /** + * Writes an api call to the endpoint of a device. + * @param deviceName the name of the device + * @param message the JSON message + * @param responseListener the {@link Response.Listener} for defining + * actions to be performed on response + */ + public void write(final String deviceName, + final JSONObject message, + final Response.Listener responseListener) { + String url = "http://" + address + + ":" + port + + "/device/" + deviceName + "/"; JsonObjectRequest request = new JsonObjectRequest( Request.Method.POST, - requestString, + url, message, responseListener, - error -> { - Log.e("Communicator", "Error during WRITE: " + error.getMessage()); error.printStackTrace(); } + error -> Log.e("Communicator", + "Error during WRITE: " + error.getMessage()) ); requestQueue.add(request); } - public void uploadXML(File xmlFile) { - throw new NotImplementedError(); + /** + * Uploads the config.xml file to the raspberry. + */ + public void uploadXML() throws FileNotFoundException { + File xmlFile = new File(ExternalStorageHandler + .getExternalPrivateStorageDir(context), "config.xml"); + String url = "http://" + address + ":" + port + "/XML/"; + FileOutputVolleyRequest request = new FileOutputVolleyRequest( + Request.Method.POST, + url, + xmlFile, + response -> System.out.println(response.toString()), + error -> Log.e("Communicator", + "Error during XML UPLOAD" + error.getMessage()) + ); + requestQueue.add(request); } + /** + * Downloads the config.xml file from the raspberry. + */ public void downloadXML() { - throw new NotImplementedError(); + String url = "http://" + address + ":" + port + "/XML/"; + InputStreamVolleyRequest request = new InputStreamVolleyRequest( + Request.Method.GET, + url, + response -> { + try { + if (response != null) { + String xmlPath = ExternalStorageHandler + .getExternalPrivateStorageDir(context); + File xmlFile = new File(xmlPath, "config.xml"); + /*create the default XML config by using the + default.xml from the assets folder*/ + if (xmlFile.exists()) { + xmlFile.delete(); + } + FileOutputStream fileOutputStream = + new FileOutputStream(xmlFile); + fileOutputStream.write(response); + fileOutputStream.close(); + } + } catch (IOException e) { + Log.e("Communicator", + "Error while reading the XML DOWNLOAD " + + "from the raspberry: " + + e.getMessage()); + } + }, + error -> Log.e("Communicator", + "Error during XML DOWNLOAD: " + error.getMessage()) + ); + requestQueue.add(request); } } diff --git a/APED/app/src/main/java/com/example/aped/communication/FileOutputVolleyRequest.java b/APED/app/src/main/java/com/example/aped/communication/FileOutputVolleyRequest.java new file mode 100644 index 0000000..b05ff56 --- /dev/null +++ b/APED/app/src/main/java/com/example/aped/communication/FileOutputVolleyRequest.java @@ -0,0 +1,121 @@ +package com.example.aped.communication; + +import android.util.Log; + +import com.android.volley.AuthFailureError; +import com.android.volley.NetworkResponse; +import com.android.volley.Request; +import com.android.volley.Response; +import com.android.volley.toolbox.HttpHeaderParser; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.util.Map; + +/** + * Custom {@link Request} to send xml files to the raspberry pi. + */ +public class FileOutputVolleyRequest extends Request { + + /** Listener for response callback. **/ + private final Response.Listener listener; + + /** File to be sent. **/ + private final File file; + + /** Headers of the response recieved from the raspberry. **/ + private Map responseHeaders; + + /** + * Constructor. + * @param method {@link Request.Method} + * @param url url the request will be sent to + * @param pFile the file that will be sent + * @param pListener a listener for the response callback + * @param errorListener a listener for an error callback + */ + public FileOutputVolleyRequest(final int method, + final String url, + final File pFile, + final Response.Listener pListener, + final Response.ErrorListener errorListener) { + super(method, url, errorListener); + setShouldCache(false); + this.listener = pListener; + this.file = pFile; + } + + /** + * Overrides for the body content type. + * @return xml body content type + */ + @Override + public String getBodyContentType() { + return "application/xml; charset = utf-8"; + } + + /** + * Defines the body content. + * @return the body content + * @throws AuthFailureError + */ + @Override + public byte[] getBody() throws AuthFailureError { + try { + BufferedReader bufferedReader = new BufferedReader( + new FileReader(file) + ); + StringBuilder stringBuilder = new StringBuilder(); + String line; + while ((line = bufferedReader.readLine()) != null) { + stringBuilder.append(line); + stringBuilder.append("\n"); + } + bufferedReader.close(); + String requestBody = stringBuilder.toString(); + return requestBody.getBytes("utf-8"); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + /** + * Parses the response into an {@link JSONObject}. + * @param response the response from the raspberry + * @return a {@link Response} + */ + @Override + protected Response parseNetworkResponse( + final NetworkResponse response) { + responseHeaders = response.headers; + + JSONObject obj = null; + try { + obj = new JSONObject(new String(response.data)); + } catch (JSONException e) { + Log.e("FileOutputVolleyRequest", + "Failed parsing JSON:" + e.getMessage()); + } + return Response.success( + obj, HttpHeaderParser.parseCacheHeaders(response) + ); + } + + /** + * Deliveres the Response to the response listener. + * @param response the parsed response + */ + @Override + protected void deliverResponse(final JSONObject response) { + listener.onResponse(response); + } +} diff --git a/APED/app/src/main/java/com/example/aped/communication/InputStreamVolleyRequest.java b/APED/app/src/main/java/com/example/aped/communication/InputStreamVolleyRequest.java new file mode 100644 index 0000000..090a2c1 --- /dev/null +++ b/APED/app/src/main/java/com/example/aped/communication/InputStreamVolleyRequest.java @@ -0,0 +1,60 @@ +package com.example.aped.communication; + +import com.android.volley.NetworkResponse; +import com.android.volley.Request; +import com.android.volley.Response; +import com.android.volley.toolbox.HttpHeaderParser; + +import java.util.Map; + +/** + * Custom {@link Request} to enable recieving files from the raspberry pi. + * Credit: https://mobikul.com/downloading-files-using-volley/ + */ +public class InputStreamVolleyRequest extends Request { + + /** Listerner for response callback. **/ + private final Response.Listener listener; + + /** Headers of the response recieved from the raspberry.**/ + private Map responseHeaders; + + /** + * Constructor. + * @param method {@link Request.Method} + * @param url the API url to send the request to + * @param pListener the listener for the response callback + * @param errorListener the listener for an error callback + */ + public InputStreamVolleyRequest(final int method, + final String url, + final Response.Listener pListener, + final Response.ErrorListener errorListener) { + super(method, url, errorListener); + setShouldCache(false); + this.listener = pListener; + } + + /** + * Parses the response into a byte array. + * @param response the response recieved from the raspberry + * @return the parsed response + */ + @Override + protected Response parseNetworkResponse( + final NetworkResponse response) { + responseHeaders = response.headers; + return Response.success( + response.data, HttpHeaderParser.parseCacheHeaders(response) + ); + } + + /** + * Delivers the recieved response to the listener. + * @param response the parsed response + */ + @Override + protected void deliverResponse(final byte[] response) { + listener.onResponse(response); + } +}