/** * Copyright (C) 2013 - 2015 the enviroCar community * * This file is part of the enviroCar app. * * The enviroCar app is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The enviroCar app is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along * with the enviroCar app. If not, see http://www.gnu.org/licenses/. */ package org.envirocar.app.events; import android.location.Location; import android.os.SystemClock; import com.mapbox.mapboxsdk.overlay.PathOverlay; import com.squareup.otto.Bus; import com.squareup.otto.Produce; import com.squareup.otto.Subscribe; import org.envirocar.core.entity.Measurement; import org.envirocar.core.events.NewMeasurementEvent; import org.envirocar.core.events.gps.GpsLocationChangedEvent; import org.envirocar.core.logging.Logger; import rx.Scheduler; import rx.android.schedulers.AndroidSchedulers; /** * @author dewall */ public class TrackDetailsProvider { private static final Logger LOGGER = Logger.getLogger(TrackDetailsProvider.class); private final Scheduler.Worker mMainThreadWorker = AndroidSchedulers .mainThread().createWorker(); private PathOverlay mTrackMapOverlay = new PathOverlay(); private int mNumMeasurements; private double mDistanceValue; private double mTotalSpeed; private int mAvrgSpeed; private long mStartingBaseTime; private Location mLastLocation; private Location mCurrentLocation; private final Bus mBus; /** * Constructor. * * @param bus */ public TrackDetailsProvider(Bus bus) { this.mBus = bus; // we do not need to register on the bus! } // @Subscribe // public void onReceiveBluetoothServiceStateChangedEvent( // BluetoothServiceStateChangedEvent event) { // LOGGER.info(String.format("Received event: %s", event.toString())); // mMainThreadWorker.schedule(() -> { // if (event.mState == BluetoothServiceState.SERVICE_STOPPED) { // mTrackMapOverlay.clearPath(); // mNumMeasurements = 0; // mDistanceValue = 0; // mTotalSpeed = 0; // mAvrgSpeed = 0; // mStartingBaseTime = 0; // mLastLocation = null; // mCurrentLocation = null; // } // }); // } @Subscribe public void onReceiveLocationChangedEvent(GpsLocationChangedEvent event) { LOGGER.debug(String.format("Received event: %s", event.toString())); } @Subscribe public void onReceiveNewMeasurementEvent(NewMeasurementEvent event) { LOGGER.debug(String.format("Received event: %s", event.toString())); if (mNumMeasurements == 0) { mStartingBaseTime = SystemClock.elapsedRealtime(); mBus.post(new StartingTimeEvent(mStartingBaseTime, true)); } mNumMeasurements++; // update computed features updateDistance(event.mMeasurement); updateAverageSpeed(event.mMeasurement); updatePathOverlay(event.mMeasurement); } @Produce public TrackPathOverlayEvent provideTrackPathOverlay() { return new TrackPathOverlayEvent(mTrackMapOverlay); } @Produce public DistanceValueUpdateEvent provideDistanceValue() { return new DistanceValueUpdateEvent(mDistanceValue); } @Produce public AvrgSpeedUpdateEvent provideAverageSpeed() { return new AvrgSpeedUpdateEvent(mAvrgSpeed); } @Produce public StartingTimeEvent provideStartingTime() { if (mStartingBaseTime == 0) return new StartingTimeEvent(SystemClock.elapsedRealtime(), false); return new StartingTimeEvent(mStartingBaseTime, true); } private void updatePathOverlay(Measurement measurement) { mMainThreadWorker.schedule(() -> { mTrackMapOverlay.addPoint(measurement.getLatitude(), measurement.getLongitude()); }); } /** * Updates the distance value based on the new measurements location and the location of the * previous location. * * @param measurement the measurement to compute the distance relative to the last measurement. */ private void updateDistance(Measurement measurement) { if (mLastLocation == null) { mLastLocation = new Location("GPS"); mLastLocation.setLatitude(measurement.getLatitude()); mLastLocation.setLongitude(measurement.getLongitude()); } else { mCurrentLocation = new Location("GPS"); mCurrentLocation.setLatitude(measurement.getLatitude()); mCurrentLocation.setLongitude(measurement.getLongitude()); // Compute the distance between the last location and the new location. float[] res = new float[1]; Location.distanceBetween( mLastLocation.getLatitude(), mLastLocation.getLongitude(), mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude(), res); // update the distance value if (res[0] > 0) { mDistanceValue += res[0] / 1000; mBus.post(provideDistanceValue()); } mLastLocation = mCurrentLocation; mCurrentLocation = null; } } /** * @param measurement */ private void updateAverageSpeed(Measurement measurement) { if (measurement.hasProperty(Measurement.PropertyKey.SPEED)){ mTotalSpeed += measurement.getProperty(Measurement.PropertyKey.SPEED); mAvrgSpeed = (int) mTotalSpeed / mNumMeasurements; mBus.post(provideAverageSpeed()); } } public void clear() { mMainThreadWorker.schedule(() -> { mTrackMapOverlay.clearPath(); mNumMeasurements = 0; mDistanceValue = 0; mTotalSpeed = 0; mAvrgSpeed = 0; mStartingBaseTime = 0; mLastLocation = null; mCurrentLocation = null; }); } }