/* This file is part of Wattzap Community Edition.
*
* Wattzap Community Edtion 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.
*
* Wattzap Community Edition 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 Wattzap. If not, see <http://www.gnu.org/licenses/>.
*/
package com.wattzap.model.ant;
import java.math.BigDecimal;
import java.math.RoundingMode;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import com.wattzap.controller.MessageBus;
import com.wattzap.controller.MessageCallback;
import com.wattzap.controller.Messages;
import com.wattzap.model.RouteReader;
import com.wattzap.model.UserPreferences;
import com.wattzap.model.dto.Point;
import com.wattzap.model.dto.Telemetry;
import com.wattzap.model.power.Power;
import com.wattzap.utils.Rolling;
/**
* (c) 2013 David George / WattzAp.com
*
* Speed and Cadence ANT+ processor.
*
* @author David George
* @date 11 June 2013
*/
public class DummySpeedCadenceListener extends Thread implements
MessageCallback {
private boolean running = true;
private double distance = 0.0;
private final UserPreferences userPrefs = UserPreferences.INSTANCE;
RouteReader routeData = null;
Rolling rPower;
double mass;
double wheelSize;
int resistance;
Power power;
boolean virtualPower;
private static Logger logger = LogManager
.getLogger("DummySpeedCadenceListener");
public DummySpeedCadenceListener() {
MessageBus.INSTANCE.register(Messages.START, this);
MessageBus.INSTANCE.register(Messages.STARTPOS, this);
MessageBus.INSTANCE.register(Messages.STOP, this);
MessageBus.INSTANCE.register(Messages.GPXLOAD, this);
}
public void run() {
while (true) {
// sleep first
try {
Thread.sleep(250);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (running) {
Point p;
Telemetry t = new Telemetry();
// half FTP
// int powerWatts = (int)
// ((userPrefs.getMaxPower() + (Math
// .random() * 10)) * 0.5);
int powerWatts = (int) (userPrefs.getMaxPower() * 0.5);
double speed = 0;
// if ant disabled always use this calculation
if ((virtualPower || !userPrefs.isAntEnabled())
&& routeData != null) {
if (routeData.routeType() == RouteReader.SLOPE) {
p = routeData.getPoint(distance);
/*
* increase power for hills to FTP
*/
if (p != null) {
powerWatts += powerWatts
* (p.getGradient() / routeData
.getMaxSlope());
if (userPrefs.getResistance() == power.getResitanceLevels() ) {
// AUTO
int r = power.getResistance(p.getGradient());
t.setResistance(r);
speed = power.getSpeed(powerWatts, r);
} else {
// speed corresponding to this power
speed = power.getSpeed(powerWatts,
userPrefs
.getResistance());
}
BigDecimal bd = new BigDecimal(speed).setScale(2,
RoundingMode.HALF_UP);
t.setVirtualSpeed(bd.intValue());
// we need to now calculate video speed but we need
// to
// display real speed
// what would be our real speed for those watts -
// show
// in odo
double realSpeed = power.getRealSpeed(mass,
p.getGradient() / 100, powerWatts);
speed = (realSpeed * 3600) / 1000;
}
} else {
// here we are a power file
// TODO For power files we just want to play at normal
// speed. OK we no there is no ANT here.
p = routeData.getPoint(distance);
// power comes from video (gradient)
// powerWatts = (int) ((p.getGradient()) +
// (Math.random() * 4));
powerWatts = (int) p.getPower();
// apply some smoothing
rPower.add(powerWatts);
powerWatts = (int) rPower.getAverage();
if (userPrefs.getResistance() == 0) {
t.setResistance(1);
speed = power.getSpeed(powerWatts, 1);
} else {
// speed corresponding to this power
speed = power.getSpeed(powerWatts,
userPrefs.getResistance());
BigDecimal bd = new BigDecimal(speed).setScale(2,
RoundingMode.HALF_UP);
t.setVirtualSpeed(bd.intValue());
t.setResistance(userPrefs
.getResistance());
if (routeData.getExtension().equals("pwr")) {
speed = p.getSpeed();
}
}
}
} else {
speed = power.getRealSpeed(mass, 0, powerWatts) * 3.6;
}
t.setPower(powerWatts);
if (routeData != null) {
p = routeData.getPoint(distance);
if (p == null) {
// end of the road
t.setDistanceMeters(distance * 1000);
distance = 0.0;
t.setSpeed(0);
t.setTime(System.currentTimeMillis());
MessageBus.INSTANCE.send(Messages.SPEED, t);
return;
}
t.setElevation(p.getElevation());
t.setGradient(p.getGradient());
t.setLatitude(p.getLatitude());
t.setLongitude(p.getLongitude());
}
t.setSpeed(speed);
t.setDistanceMeters(distance * 1000);
t.setTime(System.currentTimeMillis());
MessageBus.INSTANCE.send(Messages.SPEED, t);
// d = s * t
distance += (speed / 3600) * 0.25;
}
}
}
public void callback(Messages message, Object o) {
switch (message) {
case START:
// get uptodate values
mass = userPrefs.getTotalWeight();
wheelSize = userPrefs.getWheelSizeCM();
resistance = userPrefs.getResistance();
power = userPrefs.getPowerProfile();
virtualPower = userPrefs.isVirtualPower();
if (this.getState() == Thread.State.NEW) {
start();
}
running = true;
break;
case STOP:
running = false;
break;
case STARTPOS:
distance = (Double) o;
break;
case GPXLOAD:
// code to see if we are registered
if (!userPrefs.isRegistered()
&& (userPrefs.getEvalTime()) <= 0) {
logger.info("Out of time "
+ userPrefs.getEvalTime());
userPrefs.shutDown();
System.exit(0);
}
this.routeData = (RouteReader) o;
power = userPrefs.getPowerProfile();
power.setGrades(routeData.getMaxSlope(), routeData.getMinSlope());
distance = 0.0;
rPower = new Rolling(10);
break;
}
}
}