package com.umich.umd.obdpractice; import java.io.BufferedReader; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import android.os.AsyncTask; import android.os.Bundle; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.util.Base64; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.EditText; //import android.view.View.OnClickListener; //import android.widget.Button; //import android.widget.EditText; import android.widget.TextView; import android.support.v4.app.NavUtils; public class NetworkSetupActivity extends Activity { /**************************** Network Setup Activity Variables *************************/ // Debug tag for identifying from which activity debug message // originated private static final String DEBUG_TAG = "NetworkConnect"; // private static final String SCHEME_TYPE = "http"; // Default address for the Gryphon private static final String GRYPH_IP = "http://192.168.0.112"; // PHP Script call for grabbing list of log files stored on the Gryphon private static final String LIST_LOG_FILE_SCRIPT = "/sysadmin/playback_action.php"; // PHP Script call for downloading a specific log file from the Gryphon private static final String DOWNLOAD_LOG_FILE_SCRIPT = "/sysadmin/log_action.php"; // Parameters for listing log files stored on the Gryphon private static final String LIST_LOGS_PARAMS = "?verb=list&uploaddir=/data/&extension=.log"; // Parameters for downloading log files stored on the Gryphon private static final String DOWNLOAD_LOG_PARAMS = "?uploaddir=/data/&extension=.log&type=ascii&name="; // Final verb parameter for downloading log files private static final String DOWNLOAD_VERB = "&verb=Download"; public static final String PARSED_PREFIX = "p"; // Tag to identify json output argument for activity switch private final static String TAG_JSON_OUTPUT = "json_string"; // Filename for downloaded log files. May contain duplicates private final static String DOWNLOADED_LOG_FILES = "downloaded_logs"; // User name and password for Gryphon connection authentication private final static String USERNAME = "sysadmin"; private final static String PASSWORD = "dggryphon"; // Flags for type of request made to the Gryphon private final static int PICK_FILE_REQUEST = 0; private final static int DOWNLOAD_FILE_REQUEST = 1; // Flag generated for the current request from the App private static int CURRENT_REQUEST = 0; // Flag for determining if a log file has been chosen for download private boolean log_file_picked = false; // The base name for the most currently selected log file private static String curr_log_file_base_name = null; // The base name for the previously selected log file private static String last_log_file_base_name = null; // Debugging flag for Gryphon connection authentication private boolean accessAuthenticated = false; // TextView for displaying Network setup results private TextView displayText; // EditText view for grabbing the IP address of the Gryphon private EditText ipText; /************************* End of Network Setup Activity Variables ********************/ /************************* File Parsing Variables **************************************/ // Reader for parsing data read from Gryphon files BufferedReader reader; // The line currently being read from the log file String line; // Integer conversion of last read line int lineInt; // Data pulled from the log file String date = null; int length; // The vehicle speed pulled from the current line as integer int vehSpd_int; // The vehicle speed pulled from the current line as float float vehSpd_flt; // The engine coolant temperature pulled from the current line as integer int eng_cool_temp_int; // The engine coolant temperature pulled from the current line as float float eng_cool_temp_flt; // The fuel flow from the current line as integer int fuel_flow_int; // The fuel flow from the current line as float float fuel_flow_flt; // Conversion of read vehicle speed as string String vehSpd_str; // Conversion of read vehicle engine coolant temperature as string String eng_cool_temp_str; // Conversion of read fuel flow as string String fuel_flow_str; // Lists for holding all read vehicle speeds, eng. coolant temps, and fuel // flow values ArrayList<Integer> CAN_VEH_SPD = new ArrayList<Integer>(); ArrayList<Integer> CAN_ENG_COOL_TEMP = new ArrayList<Integer>(); ArrayList<Float> CAN_FUEL_FLOW = new ArrayList<Float>(); int i = 0; int j = 0; int k = 0; /************************** End of Log File Parsing Variables **************************/ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_network_setup); // Show the Up button in the action bar. getActionBar().setDisplayHomeAsUpEnabled(true); findViewsById(); } /** * Assign View fields to class accessible variables */ private void findViewsById() { displayText = (TextView) findViewById(R.id.fileText); ipText = (EditText) findViewById(R.id.networkIP); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_network_setup, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: // This ID represents the Home or Up button. In the case of this // activity, the Up button is shown. Use NavUtils to allow users // to navigate up one level in the application structure. For // more details, see the Navigation pattern on Android Design: // // http://developer.android.com/design/patterns/navigation.html#up-vs-back // NavUtils.navigateUpFromSameTask(this); return true; } return super.onOptionsItemSelected(item); } /** * Android tutorial based function, ignore * * @param view */ /* * public void connectToGryphon(View view) { * * String stringURL = urlText.getText().toString(); * * ConnectivityManager connMgr = * (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); * * NetworkInfo networkInfo = connMgr.getActiveNetworkInfo(); * * if(networkInfo != null && networkInfo.isConnected()) { //new * DownloadWebpageText().execute(stringURL); * * } else { textView.setText("No network connection available."); } } */ /** * * @author AbsElite * */ private class GetXMLTask extends AsyncTask<String, Void, String> { /** * */ protected String doInBackground(String... urls) { String output = null; for (String url : urls) { output = getOutputFromUrl(url); } return output; } protected String getOutputFromUrl(String url) { Log.d(DEBUG_TAG, "Attempting to instantiate StringBuffer"); StringBuffer output = new StringBuffer(""); Log.d(DEBUG_TAG, "StringBufferIn"); try { Log.d(DEBUG_TAG, "Trying Input Stream"); InputStream stream = getHttpConnection(url); Log.d(DEBUG_TAG, "InputStream successful"); int count = 0; Log.d(DEBUG_TAG, "Trying stream availability check."); while (stream.available() != 0 && count < 20) { Log.d(DEBUG_TAG, "Stream not available. Waiting"); this.wait(100); count += 1; } ; if (count > 19) { Log.e(DEBUG_TAG, "HttpConnection stream didn't become available"); finish(); } Log.d(DEBUG_TAG, "HttpStream available"); Log.d(DEBUG_TAG, "Preparing to initiate BufferedReader"); BufferedReader buffer = new BufferedReader( new InputStreamReader(stream)); Log.d(DEBUG_TAG, "BufferedReader instantiated"); String s = ""; while ((s = buffer.readLine()) != null) output.append(s + "\n"); } catch (IOException e1) { e1.printStackTrace(); } catch (NullPointerException ex) { Log.e(DEBUG_TAG, "NullPointer found in BufferedReader", ex); ex.printStackTrace(); } catch (InterruptedException e) { Log.d(DEBUG_TAG, "Wait in getOutputFromURL Interrupted", e); e.printStackTrace(); } return output.toString(); } private InputStream getHttpConnection(String urlString) throws IOException { InputStream stream = null; HttpURLConnection httpConnection; URL url; String userPassword, encoding; // prepare authorization string using android.util.Base64 userPassword = String.format("%s:%s", USERNAME, PASSWORD); int flags = Base64.NO_WRAP | Base64.URL_SAFE; encoding = Base64.encodeToString(userPassword.getBytes(), flags); // Used android based Base64 encoder instead of sun encoder // Expected to perform better than Sun version // encoding = new // sun.misc.BASE64Encoder().encode(userPassword.getBytes()); try { // Use built in functions of url to convert url string to html // encoded version url = new URL(urlString); URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef()); url = uri.toURL(); Log.d(DEBUG_TAG, "The current URL is: " + url.toString()); // Open HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection(); // Append authorization string to HTTP request header if (!accessAuthenticated) { httpConnection.setRequestProperty("Authorization", "Basic " + encoding); // accessAuthenticated = true; } /* * From open Tutorials example, using DGTech solution * httpConnection.setRequestMethod("GET"); * httpConnection.connect(); */ if (httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK) { Log.d(DEBUG_TAG, "HttpURLConnection: HTTP_OK"); stream = httpConnection.getInputStream(); Log.d(DEBUG_TAG, "Stream for httpConnection set"); } } catch (MalformedURLException ex) { Log.e(DEBUG_TAG, "Malformed URL", ex); ex.printStackTrace(); } catch (URISyntaxException e) { Log.e(DEBUG_TAG, "URI to URL convetsion failed", e); e.printStackTrace(); } return stream; } @Override protected void onPostExecute(String output) { if (CURRENT_REQUEST == PICK_FILE_REQUEST) { Intent filesListIntent = new Intent(getApplicationContext(), LogFilesList.class); filesListIntent.putExtra(TAG_JSON_OUTPUT, output); startActivityForResult(filesListIntent, PICK_FILE_REQUEST); } else { try { displayText.setText(""); writeToFile(output); parseLogFile(output); FileOutputStream dlLogFile = openFileOutput( curr_log_file_base_name + ".txt", Context.MODE_PRIVATE); dlLogFile.write(output.getBytes()); dlLogFile.close(); // readText.setText("File download successful: "+ // curr_log_file_base_name); writeToFile(curr_log_file_base_name, DOWNLOADED_LOG_FILES); last_log_file_base_name = curr_log_file_base_name; curr_log_file_base_name = null; } catch (Exception e) { Log.e(DEBUG_TAG, "Error while saving log to file", e); } } } } public void pickLogFile(View view) { CURRENT_REQUEST = PICK_FILE_REQUEST; String listLogsURLString = GRYPH_IP + LIST_LOG_FILE_SCRIPT + LIST_LOGS_PARAMS; Log.d(DEBUG_TAG, "The list log URL is:" + listLogsURLString); GetXMLTask task = new GetXMLTask(); task.execute(new String[] { listLogsURLString }); } public void downloadFile(View view) { if (log_file_picked) { CURRENT_REQUEST = DOWNLOAD_FILE_REQUEST; String downloadLogURLString = GRYPH_IP + DOWNLOAD_LOG_FILE_SCRIPT + DOWNLOAD_LOG_PARAMS + curr_log_file_base_name + DOWNLOAD_VERB; Log.d(DEBUG_TAG, "The download URL is:" + downloadLogURLString); displayText.setText(downloadLogURLString); GetXMLTask task = new GetXMLTask(); task.execute(new String[] { downloadLogURLString }); log_file_picked = false; } else { displayText .setText("No File Picked. Please Choose a Log File First"); } } protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == PICK_FILE_REQUEST) { if (resultCode == RESULT_OK) { // A file was picked, display it to the user curr_log_file_base_name = data.getStringExtra("file"); displayText.setText(curr_log_file_base_name); log_file_picked = true; } } } private void writeToFile(String data) { try { OutputStreamWriter outputStreamWriter = new OutputStreamWriter( openFileOutput(curr_log_file_base_name, Context.MODE_PRIVATE)); outputStreamWriter.write(data); Log.d(DEBUG_TAG, "Output written to " + curr_log_file_base_name); outputStreamWriter.close(); } catch (IOException e) { Log.e(DEBUG_TAG, "File write failed: " + e.toString()); } } private void writeToFile(String data, String filename) { try { OutputStreamWriter outputStreamWriter = new OutputStreamWriter( openFileOutput(filename, Context.MODE_APPEND)); outputStreamWriter.write(data + "\n"); outputStreamWriter.close(); } catch (IOException e) { Log.e(DEBUG_TAG, "File write failed: " + e.toString()); } } private void parseLogFile(String data) { FileOutputStream fos = null; InputStream fis = null; try { fos = openFileOutput(PARSED_PREFIX + curr_log_file_base_name, Context.MODE_PRIVATE); fis = openFileInput(curr_log_file_base_name); reader = new BufferedReader(new InputStreamReader(fis)); while ((line = reader.readLine()) != null) { // Log.d(DEBUG_TAG, "The line read is " + lineInt); // line = ((Integer) lineInt).toString(); // Log.d(DEBUG_TAG, "The line is " + line); if (line.contains("Trigger occurred at")) { date = line; date = date.replaceAll("/", ""); date = date.replaceAll("Trigger occurred at", ""); date = date.substring(13, 21); // Log.d(DEBUG_TAG, "Date Found: " + date); } else if (line.length() == 0) { // Log.d(DEBUG_TAG, "No information"); } else if (line.contains("Chan")) { String modLine = line.replaceAll("\\W", ""); String[] columns = modLine.split("Rx"); String CANidMsg = columns[1]; // Log.d(DEBUG_TAG, "The CANidMsg is" + CANidMsg); if ((CANidMsg.substring(0, 4)).equals("0201")) { vehSpd_str = CANidMsg.substring(12, 16); /* Log.d(DEBUG_TAG, "Found VehSpd: " + vehSpd_str); */ vehSpd_int = Integer.parseInt(vehSpd_str, 16); vehSpd_int = (int) (((vehSpd_int * 0.01) - 100) * (0.62)); CAN_VEH_SPD.add(vehSpd_int); // 4-19 /* * Log.d(DEBUG_TAG, "Value added to Array: " + * String.valueOf(vehSpd_int)); */ // fos.write((CAN_VEH_SPD.get(i).toString()).getBytes()); } else if ((CANidMsg.substring(0, 4)).equals("0420")) { eng_cool_temp_str = CANidMsg.substring(4, 6); /* * Log.d(DEBUG_TAG, "Enging Cool Temp Found" + * eng_cool_temp_str); */ eng_cool_temp_int = Integer.parseInt(eng_cool_temp_str, 16); eng_cool_temp_int = (int) (eng_cool_temp_int - 40); CAN_ENG_COOL_TEMP.add(eng_cool_temp_int); fuel_flow_str = CANidMsg.substring(8, 10); /* * Log.d(DEBUG_TAG, "Fuel Flow Found: " + * fuel_flow_str); */fuel_flow_int = Integer.parseInt(fuel_flow_str, 16); fuel_flow_flt = (float) (fuel_flow_int * 0.000020833); CAN_FUEL_FLOW.add(fuel_flow_flt); /* * textV.append(CAN_FUEL_FLOW.get(i).toString()); * textV.append("\n"); i++; */ } } } for (int a = 0; a < CAN_VEH_SPD.size(); a++) { vehSpd_flt += CAN_VEH_SPD.get(a); } vehSpd_flt = vehSpd_flt / CAN_VEH_SPD.size(); vehSpd_flt = (float) Math.round(vehSpd_flt * 100) / 100; vehSpd_str = Float.toString(vehSpd_flt); displayText.append("Vehicle Speed "); displayText.append(vehSpd_str); displayText.append("\n"); fos.write(("Date: ").getBytes()); fos.write(date.getBytes()); fos.write((" Data: Vehicle Speed ").getBytes()); fos.write(vehSpd_str.getBytes()); for (int b = 0; b < CAN_ENG_COOL_TEMP.size(); b++) { eng_cool_temp_flt += CAN_ENG_COOL_TEMP.get(b); } eng_cool_temp_flt = eng_cool_temp_flt / CAN_ENG_COOL_TEMP.size(); eng_cool_temp_str = Float.toString(eng_cool_temp_flt); displayText.append("Coolant Temp "); displayText.append(eng_cool_temp_str); displayText.append("\n"); fos.write((" Coolant Temp ").getBytes()); fos.write(eng_cool_temp_str.getBytes()); for (int c = 0; c < CAN_FUEL_FLOW.size(); c++) { fuel_flow_flt += CAN_FUEL_FLOW.get(c); } fuel_flow_flt = fuel_flow_flt / CAN_ENG_COOL_TEMP.size(); fuel_flow_str = Float.toString(fuel_flow_flt); displayText.append("Fuel Flow "); displayText.append(fuel_flow_str); displayText.append("\n"); fos.write((" Fuel Flow ").getBytes()); fos.write(fuel_flow_str.getBytes()); fos.close(); } catch (IOException e) { e.printStackTrace(); } } }