/*
* VTData - Copyright(c) 2014 Joe Pasqua
* Provided under the MIT License. See the LICENSE file for details.
* Created: Dec 31, 2014
*/
package org.noroomattheinn.visibletesla.data;
import com.google.common.collect.Range;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;
import java.util.NavigableMap;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.control.ProgressIndicator;
import org.noroomattheinn.tesla.ChargeState;
import org.noroomattheinn.tesla.StreamState;
import org.noroomattheinn.tesla.Vehicle;
import org.noroomattheinn.timeseries.Row;
import org.noroomattheinn.timeseries.RowDescriptor;
import org.noroomattheinn.utils.CalTime;
import org.noroomattheinn.utils.Executor.FeedbackListener;
import org.noroomattheinn.utils.TrackedObject;
import org.noroomattheinn.utils.Utils.Predicate;
import org.noroomattheinn.visibletesla.vehicle.VTVehicle;
import static org.noroomattheinn.tesla.Tesla.logger;
/**
* VTData: Data collection and storage for VisibleTesla
*
* @author Joe Pasqua <joe at NoRoomAtTheInn dot org>
*/
public class VTData {
/*------------------------------------------------------------------------------
*
* Constants and Enums
*
*----------------------------------------------------------------------------*/
// Data that comes from the ChargeState
public static final String VoltageKey = "C_VLT";
public static final String CurrentKey = "C_AMP";
public static final String EstRangeKey = "C_EST";
public static final String SOCKey = "C_SOC";
public static final String ROCKey = "C_ROC";
public static final String BatteryAmpsKey = "C_BAM";
// Data that comes from the StreamState
public static final String LatitudeKey = "L_LAT";
public static final String LongitudeKey = "L_LNG";
public static final String HeadingKey = "L_HDG";
public static final String SpeedKey = "L_SPD";
public static final String OdometerKey = "L_ODO";
public static final String PowerKey = "L_PWR";
static final String[] Columns = {
VoltageKey, CurrentKey, EstRangeKey, SOCKey, ROCKey, BatteryAmpsKey,
LatitudeKey, LongitudeKey, HeadingKey, SpeedKey, OdometerKey, PowerKey};
public static final RowDescriptor schema = new RowDescriptor(Columns);
/*------------------------------------------------------------------------------
*
* Internal State
*
*----------------------------------------------------------------------------*/
private final File container;
private final FeedbackListener feedbackListener;
private final VTVehicle vtVehicle;
private final Options options;
private StatsCollector statsCollector;
private StreamProducer streamProducer;
private StateProducer stateProducer;
private StatsStreamer statsStreamer;
private RestStore restStore;
private ChargeStore chargeStore;
/*==============================================================================
* ------- -------
* ------- Public Interface To This Class -------
* ------- -------
*============================================================================*/
public final TrackedObject<ChargeCycle> lastChargeCycle;
public final TrackedObject<RestCycle> lastRestCycle;
public final TrackedObject<StreamState> lastStoredStreamState;
public final TrackedObject<ChargeState> lastStoredChargeState;
public VTData(File container, Options options, VTVehicle v, FeedbackListener fl) {
this.container = container;
this.options = options;
this.vtVehicle = v;
this.lastChargeCycle = new TrackedObject<>(null);
this.lastRestCycle = new TrackedObject<>(null);
this.feedbackListener = fl;
this.lastStoredStreamState = new TrackedObject<>(new StreamState());
this.lastStoredChargeState = new TrackedObject<>(null);
}
public static class Options {
public final ObjectProperty<Range<Long>> loadPeriod;
public final IntegerProperty locMinTime;
public final IntegerProperty locMinDist;
public final BooleanProperty streamWhenPossible;
public final BooleanProperty submitAnonCharge;
public final BooleanProperty submitAnonRest;
public final BooleanProperty includeLocData;
public final DoubleProperty ditherLocAmt;
public final BooleanProperty restLimitEnabled;
public final ObjectProperty<CalTime> restLimitFrom;
public final ObjectProperty<CalTime> restLimitTo;
public Options() {
this.loadPeriod = new SimpleObjectProperty<>();
this.locMinTime = new SimpleIntegerProperty();
this.locMinDist = new SimpleIntegerProperty();
this.streamWhenPossible = new SimpleBooleanProperty();
this.submitAnonCharge = new SimpleBooleanProperty();
this.submitAnonRest = new SimpleBooleanProperty();
this.includeLocData = new SimpleBooleanProperty();
this.ditherLocAmt = new SimpleDoubleProperty();
this.restLimitEnabled = new SimpleBooleanProperty();
this.restLimitFrom = new SimpleObjectProperty<>();
this.restLimitTo = new SimpleObjectProperty<>();
}
public Options(
ObjectProperty<Range<Long>> loadPeriod,
IntegerProperty locMinTime, IntegerProperty locMinDist,
BooleanProperty streamWhenPossible,
BooleanProperty submitAnonCharge, BooleanProperty submitAnonRest,
BooleanProperty includeLocData, DoubleProperty ditherLocAmt,
BooleanProperty restLimitEnabled,
ObjectProperty<CalTime> restLimitFrom,
ObjectProperty<CalTime> restLimitTo) {
this.loadPeriod = loadPeriod;
this.locMinTime = locMinTime;
this.locMinDist = locMinDist;
this.streamWhenPossible = streamWhenPossible;
this.submitAnonCharge = submitAnonCharge;
this.submitAnonRest = submitAnonRest;
this.includeLocData = includeLocData;
this.ditherLocAmt = ditherLocAmt;
this.restLimitEnabled = restLimitEnabled;
this.restLimitFrom = restLimitFrom;
this.restLimitTo = restLimitTo;
}
}
/*------------------------------------------------------------------------------
*
* Set parameters of the VTData object
*
*----------------------------------------------------------------------------*/
public void setVehicle(Vehicle v) throws IOException {
statsCollector = new StatsCollector(
container, this, vtVehicle, options.loadPeriod.get(),
options.locMinTime, options.locMinDist);
streamProducer = new StreamProducer(vtVehicle, feedbackListener);
stateProducer = new StateProducer(vtVehicle, feedbackListener);
statsStreamer = new StatsStreamer(this, vtVehicle, options.streamWhenPossible);
initChargeStore();
initRestStore();
}
public void setWakeEarly(Predicate wakeEarly) {
statsStreamer.setWakeEarly(wakeEarly);
}
public void setPassiveCollection(Predicate pc) {
statsStreamer.setPassiveCollection(pc);
}
public void setCollectNow(TimeBasedPredicate p) {
statsCollector.setCollectNow(p);
}
/*------------------------------------------------------------------------------
*
* Upgrade related methods
*
*----------------------------------------------------------------------------*/
public boolean upgradeRequired(Vehicle v) {
return StatsCollector.upgradeRequired(container, v);
}
public boolean doUpgrade(Vehicle v) {
return StatsCollector.doUpgrade(container, v);
}
/*------------------------------------------------------------------------------
*
* Producing States and Streams
*
*----------------------------------------------------------------------------*/
public void produceStream(boolean stream) {
streamProducer.produce(stream);
}
public void produceState(Vehicle.StateType whichState, ProgressIndicator pi) {
stateProducer.produce(whichState, pi);
}
/*------------------------------------------------------------------------------
*
* Getting and Exporting Cycle information
*
*----------------------------------------------------------------------------*/
public boolean export(File file, Range<Long> exportPeriod, String[] columns) {
return statsCollector.export(file, exportPeriod, columns);
}
public boolean exportRests(File toFile, Range<Long> exportPeriod) {
return restStore.export(toFile, exportPeriod);
}
public boolean exportCharges(File toFile, Range<Long> exportPeriod) {
return chargeStore.export(toFile, exportPeriod);
}
public List<RestCycle> getRestCycles(Range<Long> period) {
return restStore.getCycles(period);
}
public List<ChargeCycle> getChargeCycles(Range<Long> period) {
return chargeStore.getCycles(period);
}
public boolean exportTripsAsKML(List<Trip> trips, File toFile) {
KMLExporter ke = new KMLExporter();
return ke.export(trips, toFile);
}
/*------------------------------------------------------------------------------
*
* Accessing stored Data
*
*----------------------------------------------------------------------------*/
/**
* Return an index on the cached rows in the data store.
*
* @return A map from time -> Row for all rows in the store
*/
public NavigableMap<Long,Row> getAllLoadedRows() {
return statsCollector.getAllLoadedRows();
}
/**
* Return an index on a set of rows covered by the period [startTime..endTime].
*
* @param startTime Starting time for the period
* @param endTime Ending time for the period
* @return A map from time -> Row for all rows in the time range
*/
public NavigableMap<Long,Row> getRangeOfLoadedRows(long startTime, long endTime) {
return statsCollector.getRangeOfLoadedRows(startTime, endTime);
}
/*------------------------------------------------------------------------------
*
* Private Utility Methods
*
*----------------------------------------------------------------------------*/
private void initRestStore() throws FileNotFoundException {
boolean needsInitialLoad = RestStore.requiresInitialLoad(
container, vtVehicle.getVehicle().getVIN());
restStore = new RestStore(
container, vtVehicle, lastRestCycle,
options.submitAnonRest,
options.includeLocData,
options.ditherLocAmt);
RestMonitor rm = new RestMonitor(
vtVehicle, lastRestCycle,
options.restLimitEnabled,
options.restLimitFrom, options.restLimitTo);
if (needsInitialLoad) {
restStore.doIntialLoad(rm, statsCollector.getFullTimeSeries());
}
}
private void initChargeStore() throws FileNotFoundException {
chargeStore = new ChargeStore(
container, vtVehicle, lastChargeCycle,
options.submitAnonCharge, options.includeLocData,
options.ditherLocAmt);
ChargeMonitor cm = new ChargeMonitor(vtVehicle, lastChargeCycle);
logger.finest("Created ChargeMonitor: " + cm);
}
/*------------------------------------------------------------------------------
*
* Helper Classes
*
*----------------------------------------------------------------------------*/
public static interface TimeBasedPredicate extends Predicate {
void setTime(long time);
}
}