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);
}
}