All Downloads are FREE. Search and download functionalities are using the official Maven repository.

decodes.consumer.ShefFormatter Maven / Gradle / Ivy

Go to download

A collection of software for aggregatting and processing environmental data such as from NOAA GOES satellites.

The newest version!
/*
*  $Id$
*
*  $Log$
*  Revision 1.5  2018/02/02 14:52:14  mmaloney
*  Attempt .E for non-GOES as long as data is regular interval.
*
*  Revision 1.4  2015/11/12 15:19:23  mmaloney
*  Added PropertySpec entries with tooltip for all props.
*  Added new siteNameType property.
*
*  Revision 1.3  2014/05/30 13:15:34  mmaloney
*  dev
*
*  Revision 1.2  2014/05/28 13:09:29  mmaloney
*  dev
*
*  Revision 1.1.1.1  2014/05/19 15:28:59  mmaloney
*  OPENDCS 6.0 Initial Checkin
*
*  Revision 1.4  2012/09/10 23:55:39  mmaloney
*  Allow operation without platform record for OutputTs.
*
*  Revision 1.3  2011/05/19 17:11:46  mmaloney
*  use TextUtil.str2Boolean
*
*  Revision 1.2  2008/05/29 22:44:18  cvs
*  dev
*
*  Revision 1.3  2006/05/11 19:45:17  mjmaloney
*  dev
*
*  Revision 1.2  2005/03/21 14:26:21  mjmaloney
*  dev
*
*  Revision 1.1  2005/02/18 14:27:32  mjmaloney
*  Created.
*
*  Revision 1.19  2005/02/11 13:35:54  mjmaloney
*  dev
*
*  Revision 1.18  2004/09/06 13:42:00  mjmaloney
*  bug-fixes
*
*  Revision 1.17  2004/08/24 21:01:37  mjmaloney
*  added javadocs
*
*  Revision 1.16  2004/07/13 14:32:07  mjmaloney
*  Fixed bug in getting shef codes for several formatters.
*
*  Revision 1.15  2004/01/13 20:34:38  mjmaloney
*  Fix for full-shef-code option.
*
*  Revision 1.14  2004/01/13 17:19:51  mjmaloney
*  Bug-fixes on DECODES 6.0 beta
*
*  Revision 1.13  2003/12/23 20:10:17  mjmaloney
*  Mods to support -a (autoinstall) feature on dbimport.
*
*  Revision 1.12  2003/11/15 20:12:02  mjmaloney
*  Use accessor methods for transport medium type.
*
*  Revision 1.11  2002/12/03 21:43:07  mjmaloney
*  *** empty log message ***
*
*  Revision 1.10  2002/12/03 21:28:47  mjmaloney
*  Added UseNesdisId property.
*
*  Revision 1.9  2002/11/01 21:38:32  mjmaloney
*  Fixed null pointer bug if there was no sensor data type.
*
*  Revision 1.8  2002/11/01 21:35:09  mjmaloney
*  release prep
*
*  Revision 1.7  2002/05/19 13:02:44  mjmaloney
*  Final TimeZone mods
*
*  Revision 1.6  2002/05/19 00:22:18  mjmaloney
*  Deprecated decodes.db.TimeZone and decodes.db.TimeZoneList.
*  These are now replaced by the java.util.TimeZone class.
*
*  Revision 1.5  2002/04/18 12:19:40  mike
*  Fixed negative number parsing problem.
*  Fixed MISSING and ERROR value problem.
*
*  Revision 1.4  2002/04/05 21:25:14  mike
*  Implement sensor-site names in all formatters.
*  Fix time-ordering.
*  Fix DirectoryConsumer move functions.
*
*  Revision 1.3  2002/03/31 21:09:35  mike
*  bug fixes
*
*  Revision 1.2  2002/02/13 20:56:33  mike
*  Modify ShefFormatter to generate both .E and .A
*
*  Revision 1.1  2001/10/05 19:21:00  mike
*  Implemented ShefFormatter
*
*/
package decodes.consumer;

import java.util.Iterator;
import java.util.Properties;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.text.NumberFormat;

import ilex.var.TimedVariable;
import ilex.var.IFlags;
import ilex.util.PropertiesUtil;
import ilex.util.Logger;
import ilex.util.TextUtil;
import decodes.db.*;
import decodes.decoder.DecodedMessage;
import decodes.decoder.TimeSeries;
import decodes.decoder.Sensor;
import decodes.datasource.RawMessage;
import decodes.datasource.UnknownPlatformException;
import decodes.util.DecodesSettings;
import decodes.util.PropertySpec;

/**
  This class formats decoded data in SHEF .A or .E lines.
  Properties honored:
  
  • dotAOnly - Forces output of .A lines even for regular interval data
  • seconds - true/false indicating whether time stamps should include seconds
  • century - true/false indicating whether time stamps should include century
  • useNesdisId - Normally site names are used, set this to true to cause the 8 hex-char NESDIS ID to be used instead
  • FullShefCode - Set to true to cause full 7-char SHEF codes to be output rather than the 2-char PE.
  • DefaultShefCode - default="xxIRZZZ", this is used to fill-in the missing parts of the SHEF code when FullSheffCode is specified.
*/ public class ShefFormatter extends OutputFormatter { private SimpleDateFormat dateFormat; private boolean dotAOnly; private java.util.TimeZone myTZ; private boolean useNesdisId; private boolean fullShefCode; private String defcode; private NumberFormat numberFormat; private PresentationGroup presGrp; private String siteNameType = null; private PropertySpec propSpecs[] = { new PropertySpec("dotAOnly", PropertySpec.BOOLEAN, "(default=false) Set to true to force .A SHEF output, even for" + " regular time series."), new PropertySpec("seconds", PropertySpec.BOOLEAN, "(default=true) Set to false to omit seconds from the time stamp."), new PropertySpec("century", PropertySpec.BOOLEAN, "(default=false) Set to true to include the century in the time stamp."), new PropertySpec("useNesdisId", PropertySpec.BOOLEAN, "(default=false) Set to true to use the GOES DCP Address in the" + " output in place of the site name."), new PropertySpec("fullShefCode", PropertySpec.BOOLEAN, "(default=false) Set to true to include the full 7-char SHEF code" + "in the output. Normally only the physical element code will be included."), new PropertySpec("sitenametype", PropertySpec.STRING, "Preferred site name type (default set in your decodes.properties)"), new PropertySpec("DefaultShefCode", PropertySpec.STRING, "(default=xxIRZZZ) If you are including the full shef code, this property allows " + "you to specify the default residual fields. Leave two char place holder" + " (xx in the default) for the Physical element code."), }; /** default constructor */ public ShefFormatter() { super(); dateFormat = new SimpleDateFormat("yyMMdd 'DH'HHmmss"); dotAOnly = false; useNesdisId = false; fullShefCode = false; defcode = "xxIRZZZ"; numberFormat = NumberFormat.getNumberInstance(); numberFormat.setGroupingUsed(false); presGrp = null; } /** Initializes the Formatter. This method is called from the static makeOutputFormatter method in this class. The RoutingSpec does not need to call it explicitly. @param type the type of this output formatter. @param tz the time zone as specified in the routing spec. @param presGrp The presentation group to handle rounding & EU conversions. @param rsProps the routing-spec properties. */ protected void initFormatter(String type, java.util.TimeZone tz, PresentationGroup presGrp, Properties rsProps) throws OutputFormatterException { myTZ = tz; this.presGrp = presGrp; dateFormat.setTimeZone(tz); String s = PropertiesUtil.getIgnoreCase(rsProps, "dotAOnly"); if (s != null) dotAOnly = TextUtil.str2boolean(s); boolean newDateFormat = false; boolean seconds = true; boolean century = false; s = PropertiesUtil.getIgnoreCase(rsProps, "seconds"); if (s != null && (s.equalsIgnoreCase("no") || s.equalsIgnoreCase("false") || s.equalsIgnoreCase("off"))) { newDateFormat = true; seconds = false; } s = PropertiesUtil.getIgnoreCase(rsProps, "century"); if (s != null && (s.equalsIgnoreCase("yes") || s.equalsIgnoreCase("true") || s.equalsIgnoreCase("on"))) { newDateFormat = true; century = true; } s = PropertiesUtil.getIgnoreCase(rsProps, "useNesdisId"); if (s == null) s = PropertiesUtil.getIgnoreCase(rsProps, "useNesdisIds"); Logger.instance().log(Logger.E_DEBUG1,"useNesdisId property is '" + s + "'"); if (s != null && (s.equalsIgnoreCase("yes") || s.equalsIgnoreCase("true") || s.equalsIgnoreCase("on"))) { useNesdisId = true; Logger.instance().log(Logger.E_DEBUG1,"Using NESDIS IDs in SHEF"); } else Logger.instance().log(Logger.E_DEBUG1,"Not using NESDIS IDs"); s = PropertiesUtil.getIgnoreCase(rsProps, "FullShefCode"); if (s != null) fullShefCode = TextUtil.str2boolean(s); s = PropertiesUtil.getIgnoreCase(rsProps, "DefaultShefCode"); if (s != null) defcode = s; if (newDateFormat) { dateFormat = new SimpleDateFormat( (century ? "yy" : "") + "yyMMdd 'DH'HHmm" + (seconds ? "ss" : "")); } siteNameType = DecodesSettings.instance().siteNameTypePreference; s = PropertiesUtil.getIgnoreCase(rsProps, "sitenametype"); if (s != null) { siteNameType = s; Logger.instance().info("ShefFormatter.init - will use siteNameType=" + siteNameType); } } /** Does nothing. */ public void shutdown() { } /** Writes the passed DecodedMessage to the passed consumer, using a concrete format. @param msg The message to output. @param consumer The DataConsumer to output to. @throws OutputFormatterException if there was a problem formatting data. @throws DataConsumerException, passed through from consumer methods. */ public void formatMessage(DecodedMessage msg, DataConsumer consumer) throws DataConsumerException, OutputFormatterException { consumer.startMessage(msg); StringBuffer sb = new StringBuffer(); RawMessage rawmsg = msg.getRawMessage(); TransportMedium tm; Platform platform = null; String platformSiteName = "unknown"; char platformType = 'R'; String dcpId = "unknown"; try { tm = rawmsg.getTransportMedium(); dcpId = tm.getMediumId(); if (tm.getMediumType().equalsIgnoreCase(Constants.medium_GoesST)) platformType = 'I'; platform = rawmsg.getPlatform(); // MJM 20151028 added siteNameType property // platformSiteName = platform.getSiteName(false); Site s = platform.getSite(); SiteName sn = s.getName(siteNameType); if (sn == null) { sn = s.getPreferredName(); Logger.instance().info("Platform '" + platform.makeFileName() + "' does not have site name " + "with type '" + siteNameType + "'. Will use " + sn.toString()); Logger.instance().debug3("Available site names are:"); for(SiteName tsn : s.getNameArray()) Logger.instance().debug3(" " + tsn.toString()); } platformSiteName = sn.getNameValue(); } catch(UnknownPlatformException e) { // throw new OutputFormatterException(e.toString()); } for(Iterator it = msg.getAllTimeSeries(); it.hasNext(); ) { TimeSeries ts = (TimeSeries)it.next(); if (ts.size() == 0) continue; Sensor sensor = ts.getSensor(); String platformName; if (useNesdisId) platformName = dcpId; else { platformName = platformSiteName; if (sensor.getSite() != null && platform != null && sensor.getSite() != platform.getSite()) { SiteName sn = sensor.getSite().getName(siteNameType); if (sn == null) sn = sensor.getSite().getPreferredName(); platformName = sn.getNameValue(); } if (platformName == null) platformName = platformSiteName; } EngineeringUnit eu = ts.getEU(); DataType dt = sensor.getDataType(Constants.datatype_SHEF); String shefCode = dt != null ? dt.getCode() : "XX"; if (fullShefCode) { StringBuffer scb = new StringBuffer(shefCode.trim()); for(int i=scb.length(); i<7; i++) scb.append(defcode.charAt(i)); shefCode = scb.toString(); } ts.sort(); //TODO // determine whether to do .A or .E // if sensor.recordingMode is F (fixed) and there are no gaps in the data, I can do .E // otherwise I have to do .A boolean doDotA = true; if (!dotAOnly && sensor.getRecordingMode() == Constants.recordingModeFixed && sensor.getRecordingInterval() > 0) { int sz = ts.size(); long lastSecTime = 0L; doDotA = false; for(int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy