package org.openmuc.framework.driver.aggregator.types;
import java.util.List;
import org.openmuc.framework.data.Record;
import org.openmuc.framework.dataaccess.Channel;
import org.openmuc.framework.dataaccess.DataAccessService;
import org.openmuc.framework.driver.aggregator.AggregationException;
import org.openmuc.framework.driver.aggregator.AggregatorChannel;
import org.openmuc.framework.driver.aggregator.AggregatorConstants;
import org.openmuc.framework.driver.aggregator.AggregatorUtil;
import org.openmuc.framework.driver.aggregator.ChannelAddress;
public class PulseEnergyAggregation extends AggregatorChannel {
private static final double SHORT_MAX = 65535.0;
private static final int INDEX_PULSES_WH = 1;
private static final int INDEX_MAX_COUNTER = 2;
public PulseEnergyAggregation(ChannelAddress simpleAddress, DataAccessService dataAccessService)
throws AggregationException {
super(simpleAddress, dataAccessService);
}
/**
* Performs aggregation
*/
@Override
public double aggregate(long currentTimestamp, long endTimestamp) throws AggregationException {
double value = 0;
try {
List<Record> recordList = getLoggedRecords(currentTimestamp, endTimestamp);
value = getPulsesEnergy(channelAddress, sourceChannel, recordList, aggregatedChannel);
} catch (Exception e) {
throw new AggregationException(e.getMessage());
}
return value;
}
private double getPulsesEnergy(ChannelAddress simpleAdress, Channel sourceChannel, List<Record> recordList,
Channel aggregatedChannel) throws AggregationException, AggregationException {
double aggregatedValue;
double pulsesPerWh;
double maxCounterValue;
// parse type address params. length = 3: <type,pulsePerWh,maxCounterValue>
String[] typeParams = simpleAdress.getAggregationType().split(AggregatorConstants.TYPE_PARAM_SEPARATOR);
if (typeParams.length == 3) {
pulsesPerWh = Double.valueOf(typeParams[INDEX_PULSES_WH]);
maxCounterValue = Double.valueOf(typeParams[INDEX_MAX_COUNTER]);
}
else {
throw new AggregationException("Wrong parameters for PULSE_ENERGY.");
}
if (pulsesPerWh > 0) {
if (maxCounterValue <= 0) {
maxCounterValue = SHORT_MAX; // if negative or null then set default value
}
aggregatedValue = getImpulsValue(sourceChannel, recordList, aggregatedChannel.getSamplingInterval(),
pulsesPerWh, maxCounterValue);
}
else {
throw new AggregationException("Parameter pulses per Wh has to be greater then 0.");
}
return aggregatedValue;
}
private double getImpulsValue(Channel sourceChannel, List<Record> recordList, long samplingInterval,
double pulsesPerX, double maxCounterValue) throws AggregationException {
if (recordList.size() < 1) {
throw new AggregationException("List holds less than 1 records, calculation of pulses not possible.");
}
Record lastRecord = AggregatorUtil.getLastRecordOfList(recordList);
double past = lastRecord.getValue().asDouble();
double actual = getWaitForLatestRecordValue(sourceChannel, lastRecord);
double power = calcPulsesValue(actual, past, pulsesPerX, samplingInterval, maxCounterValue);
return power;
}
private double calcPulsesValue(double actualPulses, double pulsesHist, double pulsesPerX, long loggingInterval,
double maxCounterValue) {
double power;
double pulses = actualPulses - pulsesHist;
if (pulses >= 0.0) {
pulses = actualPulses - pulsesHist;
}
else {
pulses = (maxCounterValue - pulsesHist) + actualPulses;
}
power = pulses / pulsesPerX * (loggingInterval / 1000.);
return power;
}
private double getWaitForLatestRecordValue(Channel sourceChannel, Record lastRecord) {
double returnValue;
do {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} while (sourceChannel.getLatestRecord().getTimestamp().equals(lastRecord.getTimestamp()));
returnValue = sourceChannel.getLatestRecord().getValue().asDouble();
return returnValue;
}
}