/* ===================================================================
* XantrexGtViewPowerDatumDataSource.java
*
* Created Aug 7, 2008 9:48:26 PM
*
* Copyright (c) 2008 Solarnetwork.net Dev Team.
*
* This program 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 2 of
* the License, or (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
* ===================================================================
*/
/* ==================================================================
* UrlDataCollector.java - Dec 9, 2009 9:46:41 AM
*
* Copyright 2007-2009 SolarNetwork.net Dev Team
*
* This program 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 2 of
* the License, or (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
* ==================================================================
* $Id$
* ==================================================================
*/
package net.solarnetwork.node.power.impl;
import net.solarnetwork.node.DataCollector;
import net.solarnetwork.node.DatumDataSource;
import net.solarnetwork.node.power.PowerDatum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.ObjectFactory;
/**
* Implementation of {@link GenerationDataSource} for the Xantrex series of
* inverters, acquiring the data by reading the files written by the freeware
* GT-View application.
*
* <p>
* It assumes the {@link DataCollector} implementation blocks until appropriate
* data is available when the {@link DataCollector#collectData()} method is
* called.
* </p>
*
* <p>
* The configurable properties of this class are:
* </p>
*
* <dl class="class-properties">
* <dt>dataCollectorFactory</dt>
* <dd>The factory for creating {@link DataCollector} instances with.
* {@link GenericObjectFactory#getObject()} will be called on each invocation of
* {@link #readCurrentConsumptionDatum()}.</dd>
* </dl>
*
* @author matt, mike
* @version 1.2
*/
public class XantrexGtViewPowerDatumDataSource implements DatumDataSource<PowerDatum> {
private static final int FRAME_IDX_PV_VOLTS = 2;
private static final int FRAME_IDX_PV_AMPS = 3;
private static final int FRAME_IDX_PV_WATTS = 5;
private static final int FRAME_IDX_AC_WATTS = 6;
private static final int FRAME_IDX_AC_VOLTS = 8;
private static final int FRAME_IDX_WH = 9;
private final Logger log = LoggerFactory.getLogger(getClass());
private ObjectFactory<DataCollector> dataCollectorFactory;
@Override
public String getUID() {
return getClass().getName();
}
@Override
public String getGroupUID() {
return null;
}
@Override
public Class<? extends PowerDatum> getDatumType() {
return PowerDatum.class;
}
@Override
public PowerDatum readCurrentDatum() {
DataCollector dataCollector = null;
String data = null;
try {
dataCollector = this.dataCollectorFactory.getObject();
dataCollector.collectData();
data = dataCollector.getCollectedDataAsString();
} finally {
if ( dataCollector != null ) {
dataCollector.stopCollecting();
}
}
if ( data == null ) {
log.warn("Null serial data received, serial communications problem");
return null;
}
return getPowerDatumInstance(data);
}
@SuppressWarnings("deprecation")
private PowerDatum getPowerDatumInstance(String data) {
if ( log.isDebugEnabled() ) {
log.debug("Raw last sample data in file: " + data);
}
String[] tokens = data.split("\t");
// only use this if DC watts is non-zero. Some junk is
// left over from previous day in other fields
Double d = getFrameDouble(tokens, FRAME_IDX_PV_WATTS);
if ( d == null || d.doubleValue() == 0.0 ) {
return null;
}
PowerDatum datum = new PowerDatum();
// Field 0: Date: unused
// Field 1: Time: unused
// Field 2: DC Volts
d = getFrameDouble(tokens, FRAME_IDX_PV_VOLTS);
if ( d != null ) {
datum.setPvVolts(d.floatValue());
if ( log.isDebugEnabled() ) {
log.debug("DC Volts: " + d);
}
}
// Field 3: DC Amps
d = getFrameDouble(tokens, FRAME_IDX_PV_AMPS);
if ( d != null ) {
datum.setPvAmps(d.floatValue());
if ( log.isDebugEnabled() ) {
log.debug("DC Amps: " + d);
}
}
// Field 4: MPPT: unused
// Field 5: DC Watts: already parsed above
// Field 7: Efficiency: unused
// Field 8: AC Volts: unused
d = getFrameDouble(tokens, FRAME_IDX_AC_VOLTS);
if ( d != null ) {
datum.setAcOutputVolts(d.floatValue());
if ( log.isDebugEnabled() ) {
log.debug("AC Volts: " + d);
}
}
// Field 6: AC Watts: used to set AC amps
d = getFrameDouble(tokens, FRAME_IDX_AC_WATTS);
if ( d != null ) {
if ( datum.getAcOutputVolts() > 0 ) {
datum.setAcOutputAmps(d.floatValue() / datum.getAcOutputVolts());
}
if ( log.isDebugEnabled() ) {
log.debug("AC Amps: " + d);
}
}
// Field 9: Cumulative AC Watts
d = getFrameDouble(tokens, FRAME_IDX_WH);
if ( d != null ) {
// store Wh as kWh
datum.setKWattHoursToday(d.doubleValue() / 1000);
if ( log.isDebugEnabled() ) {
log.debug("WH: " + d);
}
}
return datum;
}
private Double getFrameDouble(String[] frame, int idx) {
if ( frame[idx].length() > 0 ) {
return Double.valueOf(frame[idx]);
}
return null;
}
public ObjectFactory<DataCollector> getDataCollectorFactory() {
return dataCollectorFactory;
}
public void setDataCollectorFactory(ObjectFactory<DataCollector> dataCollectorFactory) {
this.dataCollectorFactory = dataCollectorFactory;
}
}