package com.integreight.onesheeld.shields.controller; import android.Manifest; import android.app.Activity; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Build; import android.os.Environment; import android.os.Vibrator; import android.support.v4.app.NotificationCompat; import android.support.v4.content.FileProvider; import android.webkit.MimeTypeMap; import android.widget.Toast; import com.integreight.onesheeld.BuildConfig; import com.integreight.onesheeld.OneSheeldApplication; import com.integreight.onesheeld.R; import com.integreight.onesheeld.enums.UIShield; import com.integreight.onesheeld.model.ArduinoConnectedPin; import com.integreight.onesheeld.sdk.ShieldFrame; import com.integreight.onesheeld.shields.ControllerParent; import com.integreight.onesheeld.utils.Log; import org.supercsv.cellprocessor.Optional; import org.supercsv.cellprocessor.ift.CellProcessor; import org.supercsv.io.CsvMapWriter; import org.supercsv.io.ICsvMapWriter; import org.supercsv.prefs.CsvPreference; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; public class DataLoggerShield extends ControllerParent<DataLoggerShield> { private static final byte START_LOGGING = 0x01; private static final byte STOP_LOGGING = 0x02; private static final byte ADD_FLOAT = 0x03; private static final byte ADD_STRING = 0x04; private static final byte LOG = 0x05; private boolean isStarted = false; public CopyOnWriteArrayList<String> headerList = new CopyOnWriteArrayList<>(); ArrayList<Map<String, String>> dataSet = new ArrayList<>(); String fileName = null; String fullFileName = null; String filePath = null; String header[]; Map<String, String> rowData = new HashMap<>(); public static final int READ_FOR_LOGGING = 0, LOGGING = 1, STOPPED_LOGGING = 2; public int currentStatus = READ_FOR_LOGGING; private DataLoggerListener eventHandler; public boolean isLoggingStarted() { return isStarted; } public DataLoggerShield() { super(); } public DataLoggerShield(Activity activity, String tag) { super(activity, tag); } @Override public void setConnected(ArduinoConnectedPin... pins) { super.setConnected(pins); } @Override public void refresh() { // TODO Auto-generated method stub } @Override public ControllerParent<DataLoggerShield> invalidate(SelectionAction selectionAction, boolean isToastable) { this.selectionAction = selectionAction; addRequiredPremission(Manifest.permission.WRITE_EXTERNAL_STORAGE); if (Build.VERSION.SDK_INT >= 16) addRequiredPremission(Manifest.permission.READ_EXTERNAL_STORAGE); if (checkForPermissions()) { if (selectionAction != null) selectionAction.onSuccess(); } else { if (selectionAction != null) selectionAction.onFailure(); } return super.invalidate(selectionAction, isToastable); } @Override public void onNewShieldFrameReceived(ShieldFrame frame) { if (frame.getShieldId() == UIShield.DATA_LOGGER.getId()) { switch (frame.getFunctionId()) { case START_LOGGING: if (frame.getArguments().size() > 0) fileName = frame.getArgumentAsString(0); else fileName = null; headerList = new CopyOnWriteArrayList<>(); dataSet = new ArrayList<>(); rowData = new HashMap<>(); currentStatus = LOGGING; isStarted = true; Log.d("HeaderSize", "Start"); if (eventHandler != null) { eventHandler.onStartLogging(); } break; case STOP_LOGGING: saveData(); break; case ADD_STRING: if (isStarted) { currentStatus = LOGGING; String key = frame.getArgumentAsString(0); String value = frame.getArgumentAsString(1); if (!headerList.contains(key)) headerList.add(key); rowData.put(key, value); if (eventHandler != null) { eventHandler.onAdd(key, value); } } break; case ADD_FLOAT: if (isStarted) { currentStatus = LOGGING; String keyFloat = frame.getArgumentAsString(0); String valueFloat = frame.getArgumentAsFloat(1) + ""; Log.d("HeaderSize", "Add : " + keyFloat + " " + valueFloat); if (!headerList.contains(keyFloat)) headerList.add(keyFloat); rowData.put(keyFloat, valueFloat); if (eventHandler != null) { eventHandler.onAdd(keyFloat, valueFloat); } } break; case LOG: if (isStarted) { currentStatus = LOGGING; if (eventHandler != null) { eventHandler.onLog(new HashMap<>(rowData)); } if (!headerList.contains("Time")) headerList.add("Time"); rowData.put("Time", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US).format(new Date()) .toString()); //rowData.remove("Time"); dataSet.add(new HashMap<>(rowData)); rowData = new HashMap<>(); Log.d("HeaderSize", "Log: " + headerList.size() + " **"); } break; default: break; } } } public void saveData() { if (isStarted) { isStarted = false; ICsvMapWriter mapWriter = null; try { currentStatus = STOPPED_LOGGING; if (eventHandler != null) { eventHandler.onStopLogging(dataSet); } File folder = new File( Environment.getExternalStorageDirectory() + "/OneSheeld"); if (!folder.exists()) { folder.mkdirs(); } folder = new File( Environment.getExternalStorageDirectory() + "/OneSheeld/DataLogger"); if (!folder.exists()) { folder.mkdirs(); } fullFileName = (fileName == null || fileName.length() == 0 ? new Date() .getTime() + "" : fileName + " - " + new Date() .getTime()) + ".csv"; filePath = Environment .getExternalStorageDirectory() + "/OneSheeld/DataLogger/" + fullFileName; mapWriter = new CsvMapWriter( new FileWriter(filePath), CsvPreference.STANDARD_PREFERENCE); final CellProcessor[] processors = new CellProcessor[headerList .size()]; for (int i = 0; i < processors.length; i++) { processors[i] = new Optional(); } // write the header header = new String[headerList.size()]; Log.d("HeaderSize", "Stop: " + headerList.size() + ""); int i = 0; for (final String headerItem : headerList) { header[i] = headerItem; i++; } if (header.length > 0) { mapWriter.writeHeader(header); // write the customer MapsaqxzheaderList for (Map<String, String> value : dataSet) { mapWriter.write(value, header, processors); } } // Toast.makeText(activity,"Data Logged Successfully.",Toast.LENGTH_SHORT).show(); showNotification(activity.getString(R.string.data_logger_data_logged_successfully_notification) + ((fullFileName == null && fullFileName.length() <= 0) ? "." : " " + activity.getString(R.string.data_logger_to) + " " + fullFileName)); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if (mapWriter != null) { try { mapWriter.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } // reset(); } } } } protected void showNotification(String notificationText) { // TODO Auto-generated method stub NotificationCompat.Builder build = new NotificationCompat.Builder( activity); build.setSmallIcon(OneSheeldApplication.getNotificationIcon()); build.setContentTitle(activity.getString(R.string.data_logger_shield_name)); build.setContentText(notificationText); build.setTicker(notificationText); build.setWhen(System.currentTimeMillis()); build.setAutoCancel(true); Toast.makeText(activity, notificationText, Toast.LENGTH_SHORT).show(); Vibrator v = (Vibrator) activity .getSystemService(Context.VIBRATOR_SERVICE); v.vibrate(1000); Intent notificationIntent = new Intent(Intent.ACTION_VIEW); MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton(); String mimeFileType = mimeTypeMap.getMimeTypeFromExtension("csv"); if(Build.VERSION.SDK_INT>=24) { Uri fileURI = FileProvider.getUriForFile(activity, BuildConfig.APPLICATION_ID + ".provider", new File(filePath == null || filePath.length() == 0 ? "" : filePath)); notificationIntent.setDataAndType(fileURI, mimeFileType); } else{ notificationIntent.setDataAndType(Uri.fromFile(new File(filePath == null || filePath.length() == 0 ? "" : filePath)), mimeFileType); } notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); notificationIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); PendingIntent intent = PendingIntent.getActivity(activity, 0, notificationIntent, 0); build.setContentIntent(intent); Notification notification = build.build(); notification.flags |= Notification.FLAG_AUTO_CANCEL; NotificationManager notificationManager = (NotificationManager) activity .getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify((int) new Date().getTime(), notification); } @Override public void reset() { saveData(); if (dataSet != null) dataSet.clear(); dataSet = null; header = null; if (headerList != null) headerList.clear(); headerList = null; } public void setEventHandler(DataLoggerListener eventHandler) { this.eventHandler = eventHandler; } public static interface DataLoggerListener { public void onStartLogging(); public void onStopLogging(ArrayList<Map<String, String>> loggedValues); public void onReadyForLogging(); public void onAdd(String key, String value); public void onLog(Map<String, String> rowData); } }