package lu.fisch.canze.classes; import android.content.res.Resources; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.Locale; import lu.fisch.canze.R; import lu.fisch.canze.activities.MainActivity; import lu.fisch.canze.actors.Field; import lu.fisch.canze.interfaces.FieldListener; import static lu.fisch.canze.activities.MainActivity.debug; /** * Created by Chris Mattheis on 03/11/15. * don't use yet - still work in progress */ public class DataLogger implements FieldListener { /* **************************** * Singleton stuff * ****************************/ private static DataLogger dataLogger = null; public static DataLogger getInstance() { if(dataLogger ==null) dataLogger =new DataLogger(); return dataLogger; } /* **************************** * Datalogger stuff * ****************************/ // -------- Data Definitions copied from Driving Activity -- start --- // for ISO-TP optimization to work, group all identical CAN ID's together when calling addListener // free data public static final String SID_Consumption = "1fd.48"; //EVC public static final String SID_Pedal = "186.40"; //EVC public static final String SID_MeanEffectiveTorque = "186.16"; //EVC public static final String SID_RealSpeed = "5d7.0"; //ESC-ABS public static final String SID_SoC = "654.25"; //EVC public static final String SID_RangeEstimate = "654.42"; //EVC public static final String SID_DriverBrakeWheel_Torque_Request = "130.44"; //UBP braking wheel torque the driver wants public static final String SID_ElecBrakeWheelsTorqueApplied = "1f8.28"; //UBP 10ms // ISO-TP data // public static final String SID_EVC_SoC = "7ec.622002.24"; // (EVC) // public static final String SID_EVC_RealSpeed = "7ec.622003.24"; // (EVC) public static final String SID_EVC_Odometer = "7ec.622006.24"; // (EVC) // public static final String SID_EVC_Pedal = "7ec.62202e.24"; // (EVC) public static final String SID_EVC_TractionBatteryVoltage = "7ec.623203.24"; // (EVC) public static final String SID_EVC_TractionBatteryCurrent = "7ec.623204.24"; // (EVC) public static final String SID_MaxCharge = "7bb.6101.336"; private double dcVolt = 0; // holds the DC voltage, so we can calculate the power when the amps come in private int odo = 0; private double realSpeed = 0; private double dcPwr = 0; private String var_SoC; private String var_Pedal; private String var_MeanEffectiveTorque; private String var_Odometer; private String var_realSpeed; private String var_Consumption; private String var_dcVolt; private String var_dcPwr; private String var_rangeInBat; private ArrayList<Field> subscribedFields; // -------- Data Definitions copied from Driving Activity -- end --- private File logFile = null; private boolean activated = false; private long z = 2; SimpleDateFormat sdf = new SimpleDateFormat(MainActivity.getStringSingle(R.string.format_YMDHMS), Locale.getDefault()); // SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.getDefault()); // Checks if external storage is available for read and write public DataLogger() { debug("DataLogger: constructor called"); } // milliSeconds == 0 --> get current time // milliSeconds > 0 --> use the time given as parameter private String getDateString(long milliSeconds, String dateFormat) { // Create a DateFormatter object for displaying date in specified format. SimpleDateFormat formatter = new SimpleDateFormat(dateFormat); // Create a calendar object that will convert the date and time value in milliseconds to date. Calendar calendar = Calendar.getInstance(); if ( milliSeconds > 0 ) { calendar.setTimeInMillis(milliSeconds); } return formatter.format(calendar.getTime()); } public boolean isExternalStorageWritable() { String SDstate = Environment.getExternalStorageState(); return ( Environment.MEDIA_MOUNTED.equals(SDstate)); } public boolean isCreated() { return (logFile!=null); } public boolean activate ( boolean state ) { boolean result = state; debug ( "DataLogger: activate > request = " + state ); if ( activated != state) { if (state) { // now need to activate, open file, start timer result = start(); activated = result; // only true in case of no errors // debug("DataLogger: start"); } else { // now need to de-activate, close file, stop timer result = stop(); activated = false; // always false // debug("DataLogger: stop "); } } debug ( "DataLogger: activate > return " + result ); return result; } public boolean createNewLog() { boolean result = false; // ensure that there is a CanZE Folder in SDcard if ( ! isExternalStorageWritable()) { debug ( "DataLogger: SDcard not writeable"); return false; } else { String file_path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/CanZE/"; File dir = new File(file_path); if (!dir.exists()) { dir.mkdirs(); } debug("DataLogger: file_path:" + file_path); // SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); String exportdataFileName = file_path + "data-" + sdf.format(Calendar.getInstance().getTime()) + ".log"; logFile = new File(exportdataFileName); if (!logFile.exists()) { try { logFile.createNewFile(); debug("DataLogger: NewFile:" + exportdataFileName ); } catch (IOException e) { e.printStackTrace(); } } try { //BufferedWriter for performance, true to set append to file flag BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(logFile, true)); // set global static BufferedWriter dataexportStream later //if (true) { // bufferedWriter.append("this is just a test if stream is writeable"); // bufferedWriter.newLine(); // bufferedWriter.close(); //} bufferedWriter.close(); result = true; } catch (IOException e) { e.printStackTrace(); } } return result; } // private long intervall = 5000; private int intervall = 5000; private Handler handler = new Handler(); private Runnable runnable = new Runnable() { @Override public void run() { // write data to file // Long tsLong = System.currentTimeMillis(); // Method 1 Long tsLong = new Date().getTime(); // Method 2 String DateString = getDateString( 0 , MainActivity.getStringSingle(R.string.format_YMDHMS)); // String DateString = getDateString( 0 , "yyyy-MM-dd-HH-mm-ss"); tsLong >>= 8; String timestamp = tsLong.toString(); // String dataWithNewLine= sdf.format(Calendar.getInstance()) + data + System.getProperty("line.separator"); // if(!isCreated()) createNewLog(); // try { // BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(logFile, true)); // bufferedWriter.append(data); // bufferedWriter.close(); //} //catch (IOException e) { // e.printStackTrace(); //} if ( realSpeed + dcPwr > 0 ) { // only log while driving or charging String dataWithNewLine = timestamp + ";" + DateString + ";" + String.format ("%.3f", realSpeed ) + ";" + String.format ("%.3f", dcPwr ) + ";" + var_SoC + ";" + var_dcVolt + ";" + var_dcPwr + ";" + var_Pedal + ";" + var_MeanEffectiveTorque + ";" + var_Odometer + ";" + var_realSpeed + ";" + var_Consumption + ";" + var_rangeInBat; log(dataWithNewLine); } handler.postDelayed(this, intervall); } }; /** * Appends a line of text to the log file * @param text the text line. A CR will be added automatically */ public void log(String text) { if(!isCreated()) createNewLog(); debug("DataLogger - log: " + text); try { BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(logFile, true)); bufferedWriter.append(text+ System.getProperty("line.separator")); bufferedWriter.close(); } catch (IOException e) { e.printStackTrace(); } } public boolean start() { boolean result = false; // open logfile // start timer debug("DataLogger: start"); handler.postDelayed(runnable, 400); initListeners(); return createNewLog(); } public boolean stop() { boolean result = false; // flush and close logfile // stop timer debug("DataLogger: stop"); logFile = null; handler.removeCallbacks(runnable); // free up the listeners again if (subscribedFields != null) { for (Field field : subscribedFields) { field.removeListener(this); } subscribedFields.clear(); } debug("DataLogger: stop - and logFile = null"); return result; } public void destroy() { handler.removeCallbacks(runnable); boolean result = stop(); } private void addListener(String sid, int intervalMs) { Field field; field = MainActivity.fields.getBySID(sid); if (field != null) { field.addListener(this); // MainActivity.device.addActivityField(field, intervalMs); MainActivity.device.addApplicationField(field, intervalMs); subscribedFields.add(field); } else { MainActivity.toast("sid " + sid + " does not exist in class Fields"); } } private void initListeners() { subscribedFields = new ArrayList<>(); debug("DataLogger: initListeners"); // Make sure to add ISO-TP listeners grouped by ID addListener(SID_Consumption, intervall ); // 2000 addListener(SID_Pedal, intervall ); // 2000 addListener(SID_MeanEffectiveTorque, intervall ); // 2000 addListener(SID_DriverBrakeWheel_Torque_Request, intervall ); // 2000 addListener(SID_ElecBrakeWheelsTorqueApplied, intervall); // 2000 addListener(SID_RealSpeed, intervall); // 2000 addListener(SID_SoC, intervall); // 3600 addListener(SID_RangeEstimate, intervall); // 3600 //addListener(SID_EVC_SoC); addListener(SID_EVC_Odometer, intervall ); // 6000 addListener(SID_EVC_TractionBatteryVoltage, intervall ); // 5000 addListener(SID_EVC_TractionBatteryCurrent, intervall ); // 2000 //addListener(SID_PEB_Torque); } // This is the event fired as soon as this the registered fields are // getting updated by the corresponding reader class. @Override public void onFieldUpdateEvent(final Field field) { String fieldId = field.getSID(); double fieldValue; // Long tsLong = System.currentTimeMillis()/1000; // String timestamp = tsLong.toString(); // String timestamp = "timestamp"; // sdf.format(sdf.format(Calendar.getInstance().getTime())); // System.getProperty("line.separator"); // log ( timestamp + ";" + fieldId + ";" + field.getPrintValue() ); // get the text field switch (fieldId) { case SID_SoC: // case SID_EVC_SoC: var_SoC = field.getPrintValue(); // log ( "...SID_SoC: " + fieldValue ); break; case SID_Pedal: // case SID_EVC_Pedal: var_Pedal = field.getPrintValue(); // pb.setProgress((int) field.getValue()); break; case SID_MeanEffectiveTorque: var_MeanEffectiveTorque = field.getPrintValue(); // pb.setProgress((int) field.getValue()); break; case SID_EVC_Odometer: odo = (int ) field.getValue(); //odo = (int) Utils.kmOrMiles(field.getValue()); var_Odometer = "" + odo; break; case SID_RealSpeed: // case SID_EVC_RealSpeed: //realSpeed = (Math.round(Utils.kmOrMiles(field.getValue()) * 10.0) / 10.0); realSpeed = (Math.round(field.getValue() * 10.0) / 10.0); var_realSpeed = "" + realSpeed; break; //case SID_PEB_Torque: // tv = (TextView) findViewById(R.id.textTorque); // break; case SID_EVC_TractionBatteryVoltage: // DC volts // save DC voltage for DC power purposes dcVolt = field.getValue(); var_dcVolt = field.getPrintValue(); break; case SID_EVC_TractionBatteryCurrent: // DC amps // calculate DC power dcPwr = Math.round(dcVolt * field.getValue() / 100.0) / 10.0; var_dcPwr = field.getPrintValue(); break; case SID_Consumption: dcPwr = field.getValue(); if (realSpeed > 5) { var_Consumption = "" + (Math.round(1000.0 * dcPwr / realSpeed) / 10.0); } else { var_Consumption = "-"; } break; case SID_RangeEstimate: //int rangeInBat = (int) Utils.kmOrMiles(field.getValue()); var_rangeInBat = "" + (int) field.getValue(); break; case SID_DriverBrakeWheel_Torque_Request: // driverBrakeWheel_Torque_Request = field.getValue(); break; case SID_ElecBrakeWheelsTorqueApplied: // double frictionBrakeTorque = driverBrakeWheel_Torque_Request - field.getValue(); // a fair full red bar is estimated @ 1000 Nm // pb = (ProgressBar) findViewById(R.id.FrictionBreaking); // pb.setProgress((int) (frictionBrakeTorque * realSpeed)); break; } } }