Issue #1011 - Corrected AIREP turbulence decoding
Change-Id: Ie56a2b916df7b68f28cca73235f33596b903c5b1 Former-commit-id:6531df3ab0
[formerlyc0e5570aa2
] [formerlyd3fd8a53df
[formerly 41dd04864bbd4b510b5e1b0c6e4259bb140b9b2e]] Former-commit-id:d3fd8a53df
Former-commit-id:029f9537c8
This commit is contained in:
parent
b93815fefd
commit
2241841dcd
10 changed files with 1000 additions and 94 deletions
|
@ -43,8 +43,9 @@ xmlns:xlink="http://www.w3.org/1999/xlink" style="stroke: rgb(255,255,255);">
|
|||
]]>
|
||||
</style>
|
||||
<symbol overflow="visible" id="plotData" class="info">
|
||||
<text id="turbInensity" plotMode="table" class="weather" plotLookupTable="airep_turb_intens_trans.txt" plotParam="FLT_HZD" x="0" y="0">0</text>
|
||||
<text id="fltLvlText" plotMode="text" plotParam="FLT_LVL" plotFormat="%3.0f" plotUnit="hft" style="text-anchor: end;" x="-15px" y="0px">75</text>
|
||||
<text id="airepturbIntensity" plotMode="table" class="weather" plotLookupTable="turb_intens_trans.txt" plotParam="TBI" x="0" y="0">0</text>
|
||||
<text id="airepturbFreq" plotMode="table" class="weather" plotLookupTable="turb_freq_trans.txt" plotParam="TBF" style="text-anchor: end" x="0" y="-10">0</text>
|
||||
<text id="airepfltLvlText" plotMode="text" plotParam="FLT_LVL" plotFormat="%3.0f" plotUnit="hft" style="text-anchor: end;" x="-15px" y="0px">75</text>
|
||||
</symbol>
|
||||
|
||||
</defs>
|
||||
|
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.9 KiB |
|
@ -3,5 +3,6 @@
|
|||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="unit-test"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
|
|
@ -12,7 +12,8 @@ Require-Bundle: org.apache.commons.logging,
|
|||
javax.measure,
|
||||
org.geotools,
|
||||
javax.persistence,
|
||||
org.apache.camel;bundle-version="1.0.0";resolution:=optional
|
||||
org.apache.camel;bundle-version="1.0.0";resolution:=optional,
|
||||
org.junit;bundle-version="1.0.0"
|
||||
Export-Package: com.raytheon.edex.plugin.airep,
|
||||
com.raytheon.edex.plugin.airep.decoder
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||
|
|
|
@ -57,6 +57,9 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader;
|
|||
* 20080103 384 jkorman Initial Coding.
|
||||
* 20080408 1039 jkorman Added traceId for tracing data.
|
||||
* 11/11/08 1684 chammack Camel Refactor
|
||||
* ======================================
|
||||
* AWIPS2 DR Work
|
||||
* 20120911 1011 jkorman Added decode of AIREP turbulence.
|
||||
* </pre>
|
||||
*
|
||||
* @author jkorman
|
||||
|
@ -99,10 +102,11 @@ public class AirepDecoder extends AbstractDecoder {
|
|||
String traceId = null;
|
||||
|
||||
try {
|
||||
// traceId = getTraceId(hdrMap);
|
||||
logger.debug(traceId + "- AirepDecoder.decode()");
|
||||
WMOHeader wmoHeader = input.wmoHeader;
|
||||
if(wmoHeader != null) {
|
||||
traceId = wmoHeader.getWmoHeader().replace(" ", "_");
|
||||
logger.info(traceId + "- AirepDecoder.decode()");
|
||||
|
||||
Calendar refTime = TimeTools.findDataTime(
|
||||
wmoHeader.getYYGGgg(), header);
|
||||
if(refTime != null) {
|
||||
|
@ -170,11 +174,28 @@ public class AirepDecoder extends AbstractDecoder {
|
|||
record.setLocation(location);
|
||||
|
||||
AIREPWeather wx = parser.getWeatherGroup();
|
||||
int flightConditions = -1;
|
||||
if (wx != null) {
|
||||
record.setFlightConditions(wx.getFlightConditions());
|
||||
flightConditions = wx.getFlightConditions();
|
||||
record.setFlightHazard(wx.getHazard());
|
||||
record.setFlightWeather(wx.getWeather());
|
||||
}
|
||||
AirepParser.Turbulence turb = parser.getTurbulence();
|
||||
int t = -1;
|
||||
if(turb != null) {
|
||||
t = turb.getTurbulence() << 4;
|
||||
}
|
||||
if(flightConditions > -1) {
|
||||
if(t > -1) {
|
||||
record.setFlightConditions(flightConditions | t);
|
||||
} else {
|
||||
record.setFlightConditions(flightConditions);
|
||||
}
|
||||
} else {
|
||||
if(t > -1) {
|
||||
record.setFlightConditions(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return record;
|
||||
|
|
|
@ -54,6 +54,9 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader;
|
|||
* ------------ ---------- ----------- --------------------------
|
||||
* 20080103 384 jkorman Initial Coding.
|
||||
* 11/13/2008 1684 chammack Camel Refactor
|
||||
* ======================================
|
||||
* AWIPS2 DR Work
|
||||
* 20120911 1011 jkorman Properly handle trailing end of report.
|
||||
* </pre>
|
||||
*
|
||||
* @author jkorman
|
||||
|
@ -69,6 +72,10 @@ public class AirepSeparator extends AbstractRecordSeparator {
|
|||
|
||||
private static final String AIREP_MSG_LINE = "(ARP|ARS)";
|
||||
|
||||
private static final String EOR_E = "=";
|
||||
|
||||
private static final String EOR_S = ";";
|
||||
|
||||
private WMOHeader wmoHeader = null;
|
||||
|
||||
private byte[] messageData = null;
|
||||
|
@ -133,6 +140,14 @@ public class AirepSeparator extends AbstractRecordSeparator {
|
|||
|
||||
if ((reports != null) && (reports.size() > 0)) {
|
||||
currentReport = 0;
|
||||
for (int i = 0; i < reports.size(); i++) {
|
||||
String s = reports.get(i);
|
||||
if (s != null) {
|
||||
if (s.endsWith(EOR_E) || s.endsWith(EOR_S)) {
|
||||
reports.set(i, s.substring(0, s.length() - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.info("No reports found in data");
|
||||
}
|
||||
|
|
|
@ -19,17 +19,19 @@
|
|||
**/
|
||||
package com.raytheon.edex.plugin.airep.decoder;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.TimeZone;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import com.raytheon.edex.esb.Headers;
|
||||
import com.raytheon.uf.common.dataplugin.airep.AirepRecord;
|
||||
import com.raytheon.uf.edex.decodertools.aircraft.AircraftFlightLevel;
|
||||
import com.raytheon.uf.edex.decodertools.aircraft.AircraftLatitude;
|
||||
import com.raytheon.uf.edex.decodertools.aircraft.AircraftLongitude;
|
||||
|
@ -37,7 +39,6 @@ import com.raytheon.uf.edex.decodertools.aircraft.AircraftRemarks;
|
|||
import com.raytheon.uf.edex.decodertools.core.BasePoint;
|
||||
import com.raytheon.uf.edex.decodertools.core.PlatformLocationProxy;
|
||||
import com.raytheon.uf.edex.decodertools.time.TimeTools;
|
||||
import com.raytheon.uf.edex.wmo.message.WMOHeader;
|
||||
|
||||
/**
|
||||
* The AirepParser takes a String that should contain a single AIREP observation
|
||||
|
@ -52,12 +53,65 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader;
|
|||
* 20080103 384 jkorman Initial Coding.
|
||||
* 20080423 1016 jkorman Added range checking for wind speed.
|
||||
* Zero'd second/milliseconds on timeObs.
|
||||
* ======================================
|
||||
* AWIPS2 DR Work
|
||||
* 20120911 1011 jkorman Added decode of AIREP turbulence, corrected
|
||||
* parse of run together latlon.
|
||||
* </pre>
|
||||
*/
|
||||
public class AirepParser {
|
||||
/** The logger */
|
||||
private Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
public static class Turbulence {
|
||||
private int turbulence = 0x80;
|
||||
|
||||
/**
|
||||
* Create an initialized turbulence object.
|
||||
*/
|
||||
public Turbulence() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the turbulence intensity.
|
||||
*
|
||||
* @param The
|
||||
* turbulence intensity.
|
||||
*/
|
||||
public void setIntensity(int intensity) {
|
||||
turbulence |= intensity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the turbulence frequency.
|
||||
*
|
||||
* @param The
|
||||
* turbulence frequency.
|
||||
*/
|
||||
public void setFrequency(int frequency) {
|
||||
turbulence |= frequency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the turbulence type.
|
||||
*
|
||||
* @param The
|
||||
* turbulence type.
|
||||
*/
|
||||
public void setType(int type) {
|
||||
turbulence |= type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the turbulence value.
|
||||
*
|
||||
* @return The turbulence value.
|
||||
*/
|
||||
public int getTurbulence() {
|
||||
return turbulence;
|
||||
}
|
||||
}
|
||||
|
||||
private static final boolean WANT_DELIMITERS = false;
|
||||
|
||||
// Only going to delimit aireps with spaces and carriage control.
|
||||
|
@ -65,6 +119,109 @@ public class AirepParser {
|
|||
|
||||
private static final int MAX_WIND_SPEED = 500;
|
||||
|
||||
private static final Set<String> TURB_TERM_WORDS = new HashSet<String>();
|
||||
static {
|
||||
TURB_TERM_WORDS.add("IC");
|
||||
TURB_TERM_WORDS.add("RM");
|
||||
TURB_TERM_WORDS.add("MID");
|
||||
TURB_TERM_WORDS.add("WX");
|
||||
|
||||
}
|
||||
|
||||
private static final Map<String, String> TURB_WORDS = new HashMap<String, String>();
|
||||
static {
|
||||
TURB_WORDS.put("TB", "TB");
|
||||
TURB_WORDS.put("TURB", "TB");
|
||||
TURB_WORDS.put("TRBC", "TB");
|
||||
}
|
||||
|
||||
private static final Map<String, Integer> TURB_TYPE = new HashMap<String, Integer>();
|
||||
static {
|
||||
TURB_TYPE.put("CAT", AirepRecord.TURB_TYPE_CAT);
|
||||
TURB_TYPE.put("CHOP", AirepRecord.TURB_TYPE_CHOP);
|
||||
TURB_TYPE.put("CHP", AirepRecord.TURB_TYPE_CHOP);
|
||||
TURB_TYPE.put("LLWS", AirepRecord.TURB_TYPE_LLWS);
|
||||
}
|
||||
|
||||
private static final Map<String, Integer> TURB_FREQ = new HashMap<String, Integer>();
|
||||
static {
|
||||
TURB_FREQ.put("OCN", AirepRecord.TURB_FREQ_OCN);
|
||||
TURB_FREQ.put("OCNL", AirepRecord.TURB_FREQ_OCN);
|
||||
TURB_FREQ.put("OCA", AirepRecord.TURB_FREQ_OCN);
|
||||
TURB_FREQ.put("OCC", AirepRecord.TURB_FREQ_OCN);
|
||||
TURB_FREQ.put("OCS", AirepRecord.TURB_FREQ_OCN);
|
||||
TURB_FREQ.put("ISO", AirepRecord.TURB_FREQ_OCN);
|
||||
|
||||
TURB_FREQ.put("INT", AirepRecord.TURB_FREQ_INT);
|
||||
TURB_FREQ.put("INTMT", AirepRecord.TURB_FREQ_INT);
|
||||
TURB_FREQ.put("INTERMITTENT", AirepRecord.TURB_FREQ_INT);
|
||||
TURB_FREQ.put("INTM", AirepRecord.TURB_FREQ_INT);
|
||||
|
||||
TURB_FREQ.put("CON", AirepRecord.TURB_FREQ_CON);
|
||||
TURB_FREQ.put("CONT", AirepRecord.TURB_FREQ_CON);
|
||||
TURB_FREQ.put("STE", AirepRecord.TURB_FREQ_CON);
|
||||
TURB_FREQ.put("CNT", AirepRecord.TURB_FREQ_CON);
|
||||
TURB_FREQ.put("CON", AirepRecord.TURB_FREQ_CON);
|
||||
TURB_FREQ.put("CONS", AirepRecord.TURB_FREQ_CON);
|
||||
TURB_FREQ.put("STD", AirepRecord.TURB_FREQ_CON);
|
||||
TURB_FREQ.put("CNS", AirepRecord.TURB_FREQ_CON);
|
||||
}
|
||||
|
||||
private static final Map<String, Integer> TURB_INT = new HashMap<String, Integer>();
|
||||
static {
|
||||
TURB_INT.put("ZERO", AirepRecord.TURB_NEG);
|
||||
TURB_INT.put("0", AirepRecord.TURB_NEG);
|
||||
TURB_INT.put("NIL", AirepRecord.TURB_NEG);
|
||||
TURB_INT.put("NEG", AirepRecord.TURB_NEG);
|
||||
TURB_INT.put("SMTH", AirepRecord.TURB_NEG);
|
||||
TURB_INT.put("SMT", AirepRecord.TURB_NEG);
|
||||
TURB_INT.put("SM H", AirepRecord.TURB_NEG);
|
||||
TURB_INT.put("NONE", AirepRecord.TURB_NEG);
|
||||
TURB_INT.put("SMOOTH", AirepRecord.TURB_NEG);
|
||||
TURB_INT.put("SMTHU", AirepRecord.TURB_NEG);
|
||||
TURB_INT.put("NEGATIVE", AirepRecord.TURB_NEG);
|
||||
|
||||
TURB_INT.put("SMOOTHLGT", AirepRecord.TURB_NEG_LGT);
|
||||
|
||||
TURB_INT.put("ONE", AirepRecord.TURB_LGT);
|
||||
TURB_INT.put("1", AirepRecord.TURB_LGT);
|
||||
TURB_INT.put("SLIGHT", AirepRecord.TURB_LGT);
|
||||
TURB_INT.put("LT", AirepRecord.TURB_LGT);
|
||||
TURB_INT.put("LGT", AirepRecord.TURB_LGT);
|
||||
TURB_INT.put("LIT", AirepRecord.TURB_LGT);
|
||||
TURB_INT.put("LIG", AirepRecord.TURB_LGT);
|
||||
TURB_INT.put("LGHT", AirepRecord.TURB_LGT);
|
||||
|
||||
TURB_INT.put("LGTMOD", AirepRecord.TURB_LGT_MOD);
|
||||
TURB_INT.put("LGT-MOD", AirepRecord.TURB_LGT_MOD);
|
||||
TURB_INT.put("SLIGHT-MOD", AirepRecord.TURB_LGT_MOD);
|
||||
|
||||
TURB_INT.put("TWO", AirepRecord.TURB_MOD);
|
||||
TURB_INT.put("2", AirepRecord.TURB_MOD);
|
||||
TURB_INT.put("MOD", AirepRecord.TURB_MOD);
|
||||
TURB_INT.put("MDT", AirepRecord.TURB_MOD);
|
||||
TURB_INT.put("TWO", AirepRecord.TURB_MOD);
|
||||
|
||||
TURB_INT.put("MODSEV", AirepRecord.TURB_MOD_SEV);
|
||||
TURB_INT.put("MODSVR", AirepRecord.TURB_MOD_SEV);
|
||||
TURB_INT.put("MDTSEV", AirepRecord.TURB_MOD_SEV);
|
||||
TURB_INT.put("MDTSVR", AirepRecord.TURB_MOD_SEV);
|
||||
TURB_INT.put("MODSEV", AirepRecord.TURB_MOD_SEV);
|
||||
TURB_INT.put("MOD-SEV", AirepRecord.TURB_MOD_SEV);
|
||||
TURB_INT.put("MDT-SEV", AirepRecord.TURB_MOD_SEV);
|
||||
TURB_INT.put("MOD-SVR", AirepRecord.TURB_MOD_SEV);
|
||||
TURB_INT.put("MDT-SVR", AirepRecord.TURB_MOD_SEV);
|
||||
|
||||
TURB_INT.put("THREE", AirepRecord.TURB_SEV);
|
||||
TURB_INT.put("3", AirepRecord.TURB_SEV);
|
||||
TURB_INT.put("SEV", AirepRecord.TURB_SEV);
|
||||
TURB_INT.put("SVR", AirepRecord.TURB_SEV);
|
||||
|
||||
TURB_INT.put("XTRM", AirepRecord.TURB_XTRM);
|
||||
TURB_INT.put("EXTRM", AirepRecord.TURB_XTRM);
|
||||
TURB_INT.put("EXTRE", AirepRecord.TURB_XTRM);
|
||||
}
|
||||
|
||||
// Once set the obs data cannot be changed!
|
||||
private final String reportData;
|
||||
|
||||
|
@ -100,7 +257,7 @@ public class AirepParser {
|
|||
final Pattern TEMP_LONG = Pattern.compile("^(MS|PS)\\d{2}");
|
||||
|
||||
// Parsed and/or decoded observation elements.
|
||||
private ArrayList<Object> theElements = new ArrayList<Object>();
|
||||
private ArrayList<Object> reportElements = new ArrayList<Object>();
|
||||
|
||||
private String aircraftId = null;
|
||||
|
||||
|
@ -116,6 +273,8 @@ public class AirepParser {
|
|||
|
||||
private Double temperature = null;
|
||||
|
||||
private Turbulence turbulence = null;
|
||||
|
||||
private AIREPWeather weatherGroup = null;
|
||||
|
||||
private Integer windDirection = null;
|
||||
|
@ -125,7 +284,6 @@ public class AirepParser {
|
|||
private AircraftRemarks rptRemarks = null;
|
||||
|
||||
private Calendar refTime;
|
||||
|
||||
|
||||
/**
|
||||
* Create the parser for and decode an observation from a String.
|
||||
|
@ -156,15 +314,12 @@ public class AirepParser {
|
|||
*/
|
||||
ArrayList<?> parseElementsTestPoint() {
|
||||
ArrayList<Object> retElements = new ArrayList<Object>();
|
||||
retElements.addAll(theElements);
|
||||
retElements.addAll(reportElements);
|
||||
return retElements;
|
||||
} // parseElementsTestPoint()
|
||||
|
||||
/**
|
||||
* Parse the AIREP observation into individual elements. Note that during
|
||||
* parse or decode the order of the elements does not change. The only
|
||||
* exception to this rule is that all elements identified as
|
||||
* comments/remarks are placed at the end of the observation elements.
|
||||
* Parse the AIREP observation into individual elements.
|
||||
*/
|
||||
private void parseElements() {
|
||||
StringTokenizer st = new StringTokenizer(reportData, DELIMITER,
|
||||
|
@ -178,7 +333,9 @@ public class AirepParser {
|
|||
if ((o != null) && (reportType == null)) {
|
||||
reportType = ((AIREPObsType) o).getValue();
|
||||
} else {
|
||||
theElements.add(s);
|
||||
if (s.length() > 0) {
|
||||
reportElements.add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -191,8 +348,8 @@ public class AirepParser {
|
|||
// run back through the data to see if there is a waypoint. If we
|
||||
// get to the time information, quit, it's not there.
|
||||
if ((latitude == null) && (longitude == null)) {
|
||||
for (int i = 0; i < theElements.size(); i++) {
|
||||
Object o = theElements.get(i);
|
||||
for (int i = 0; i < reportElements.size(); i++) {
|
||||
Object o = reportElements.get(i);
|
||||
if (o instanceof String) {
|
||||
BasePoint wayPoint = PlatformLocationProxy.lookup(
|
||||
(String) o, null);
|
||||
|
@ -220,12 +377,17 @@ public class AirepParser {
|
|||
observationTime = null;
|
||||
return;
|
||||
}
|
||||
determineAircraftId();
|
||||
|
||||
decodeFlightLevel();
|
||||
decodeTemperature();
|
||||
|
||||
decodeTurb();
|
||||
|
||||
decodeWeatherGroup();
|
||||
decodeWinds();
|
||||
|
||||
collectRemarks();
|
||||
determineAircraftId();
|
||||
} // parseElements()
|
||||
|
||||
/**
|
||||
|
@ -234,12 +396,12 @@ public class AirepParser {
|
|||
* data as the id.
|
||||
*/
|
||||
private void determineAircraftId() {
|
||||
for (int i = 0; i < theElements.size(); i++) {
|
||||
Object o = theElements.get(i);
|
||||
if (o instanceof Double) {
|
||||
for (int i = 0; i < reportElements.size(); i++) {
|
||||
Object o = reportElements.get(i);
|
||||
// Search only up to the obs time.
|
||||
if (observationTime.equals(o)) {
|
||||
break;
|
||||
}
|
||||
if (o instanceof String) {
|
||||
} else if (o instanceof String) {
|
||||
aircraftId = (String) o;
|
||||
break;
|
||||
}
|
||||
|
@ -263,13 +425,13 @@ public class AirepParser {
|
|||
* which is then processed normally.
|
||||
*/
|
||||
private void splitLatLon() {
|
||||
for (int i = 0; i < theElements.size(); i++) {
|
||||
Object o = theElements.get(i);
|
||||
for (int i = 0; i < reportElements.size(); i++) {
|
||||
Object o = reportElements.get(i);
|
||||
if (o instanceof String) {
|
||||
String[] latLon = AircraftLatitude.splitLatLon((String) o);
|
||||
if ((latLon != null)&&(latLon.length ==2)) {
|
||||
theElements.add(i, latLon[0]);
|
||||
theElements.set(i, latLon[1]);
|
||||
if ((latLon != null) && (latLon.length == 2)) {
|
||||
reportElements.set(i, latLon[1]);
|
||||
reportElements.add(i, latLon[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -283,13 +445,13 @@ public class AirepParser {
|
|||
*/
|
||||
private void decodeLatitude() {
|
||||
if (latitude == null) {
|
||||
for (int i = 0; i < theElements.size(); i++) {
|
||||
Object o = theElements.get(i);
|
||||
for (int i = 0; i < reportElements.size(); i++) {
|
||||
Object o = reportElements.get(i);
|
||||
if (o instanceof String) {
|
||||
AircraftLatitude lat = AircraftLatitude
|
||||
.aircraftLatitudeFactory((String) o);
|
||||
if (lat != null) {
|
||||
theElements.set(i, lat);
|
||||
reportElements.set(i, lat);
|
||||
latitude = lat.decodeLatitude();
|
||||
break;
|
||||
}
|
||||
|
@ -305,13 +467,13 @@ public class AirepParser {
|
|||
*/
|
||||
private void decodeLongitude() {
|
||||
if (longitude == null) {
|
||||
for (int i = 0; i < theElements.size(); i++) {
|
||||
Object o = theElements.get(i);
|
||||
for (int i = 0; i < reportElements.size(); i++) {
|
||||
Object o = reportElements.get(i);
|
||||
if (o instanceof String) {
|
||||
AircraftLongitude lon = AircraftLongitude
|
||||
.aircraftLongitudeFactory((String) o);
|
||||
if (lon != null) {
|
||||
theElements.set(i, lon);
|
||||
reportElements.set(i, lon);
|
||||
longitude = lon.decodeLongitude();
|
||||
break;
|
||||
}
|
||||
|
@ -326,8 +488,8 @@ public class AirepParser {
|
|||
* observation elements collection.
|
||||
*/
|
||||
private void decodeTime() {
|
||||
for (int i = 0; i < theElements.size(); i++) {
|
||||
Object o = theElements.get(i);
|
||||
for (int i = 0; i < reportElements.size(); i++) {
|
||||
Object o = reportElements.get(i);
|
||||
if (o instanceof String) {
|
||||
String s = (String) o;
|
||||
if (TIME.matcher(s).matches()) {
|
||||
|
@ -336,7 +498,7 @@ public class AirepParser {
|
|||
int minute = Integer.parseInt(s.substring(2));
|
||||
|
||||
if (refTime != null) {
|
||||
|
||||
|
||||
observationTime = TimeTools.copy(refTime);
|
||||
observationTime.set(Calendar.HOUR_OF_DAY, hour);
|
||||
observationTime.set(Calendar.MINUTE, minute);
|
||||
|
@ -348,7 +510,7 @@ public class AirepParser {
|
|||
observationTime.add(Calendar.DAY_OF_MONTH, -1);
|
||||
}
|
||||
|
||||
theElements.set(i, observationTime);
|
||||
reportElements.set(i, observationTime);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -357,21 +519,21 @@ public class AirepParser {
|
|||
}
|
||||
|
||||
private void decodeFlightLevel() {
|
||||
for (int i = 0; i < theElements.size(); i++) {
|
||||
Object o = theElements.get(i);
|
||||
for (int i = 0; i < reportElements.size(); i++) {
|
||||
Object o = reportElements.get(i);
|
||||
if (o instanceof String) {
|
||||
String s = (String) o;
|
||||
if (FL_SHORT.matcher(s).matches()) {
|
||||
double fLevel = Integer.parseInt(s.substring(1)) * 100;
|
||||
|
||||
flightLevel = new AircraftFlightLevel(fLevel);
|
||||
theElements.set(i, flightLevel);
|
||||
reportElements.set(i, flightLevel);
|
||||
break;
|
||||
} else if (FL_LONG.matcher(s).matches()) {
|
||||
double fLevel = Integer.parseInt(s.substring(1)) * 100;
|
||||
|
||||
flightLevel = new AircraftFlightLevel(fLevel);
|
||||
theElements.set(i, flightLevel);
|
||||
reportElements.set(i, flightLevel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -382,8 +544,8 @@ public class AirepParser {
|
|||
* Decode the temperature information in this observation.
|
||||
*/
|
||||
private void decodeTemperature() {
|
||||
for (int i = 0; i < theElements.size(); i++) {
|
||||
Object o = theElements.get(i);
|
||||
for (int i = 0; i < reportElements.size(); i++) {
|
||||
Object o = reportElements.get(i);
|
||||
if (o instanceof String) {
|
||||
double temp = Double.NaN;
|
||||
String s = (String) o;
|
||||
|
@ -396,7 +558,7 @@ public class AirepParser {
|
|||
temp *= -1;
|
||||
}
|
||||
temperature = new Double(temp);
|
||||
theElements.set(i, temperature);
|
||||
reportElements.set(i, temperature);
|
||||
}
|
||||
break;
|
||||
} else if (TEMP_SHORT.matcher(s).matches()) {
|
||||
|
@ -408,7 +570,7 @@ public class AirepParser {
|
|||
temp *= -1;
|
||||
}
|
||||
temperature = new Double(temp);
|
||||
theElements.set(i, temperature);
|
||||
reportElements.set(i, temperature);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -416,18 +578,256 @@ public class AirepParser {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode airep turbulence</br>Encoded turbulence for storage.
|
||||
* <table>
|
||||
* <tr>
|
||||
* <td>T</td>
|
||||
* <td>Int</td>
|
||||
* <td>Type</td>
|
||||
* <td>Freg</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>1</td>
|
||||
* <td>111</td>
|
||||
* <td>11</td>
|
||||
* <td>11</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td></td>
|
||||
* <td></td>
|
||||
* <td>00</td>
|
||||
* <td>no frequency</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td></td>
|
||||
* <td></td>
|
||||
* <td>01</td>
|
||||
* <td>Ocnl</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td></td>
|
||||
* <td></td>
|
||||
* <td>10</td>
|
||||
* <td>Isolated</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td></td>
|
||||
* <td></td>
|
||||
* <td>11</td>
|
||||
* <td>Continous</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td></td>
|
||||
* <td>00</td>
|
||||
* <td></td>
|
||||
* <td>No type reported</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td></td>
|
||||
* <td>01</td>
|
||||
* <td></td>
|
||||
* <td>CAT 4</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td></td>
|
||||
* <td>10</td>
|
||||
* <td></td>
|
||||
* <td>Chop 6</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td></td>
|
||||
* <td>11</td>
|
||||
* <td></td>
|
||||
* <td>LLWS 7</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td>000</td>
|
||||
* <td></td>
|
||||
* <td></td>
|
||||
* <td>No Intensity</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td>001</td>
|
||||
* <td></td>
|
||||
* <td></td>
|
||||
* <td>Smooth-Light</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td>010</td>
|
||||
* <td></td>
|
||||
* <td></td>
|
||||
* <td>Light</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td>011</td>
|
||||
* <td></td>
|
||||
* <td></td>
|
||||
* <td>Light - Mod</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td>100</td>
|
||||
* <td></td>
|
||||
* <td></td>
|
||||
* <td>Mod</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td>101</td>
|
||||
* <td></td>
|
||||
* <td></td>
|
||||
* <td>Mod - Severe</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td>110</td>
|
||||
* <td></td>
|
||||
* <td></td>
|
||||
* <td>Severe</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td></td>
|
||||
* <td>111</td>
|
||||
* <td></td>
|
||||
* <td></td>
|
||||
* <td>Extreme</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*/
|
||||
private void decodeTurb() {
|
||||
int intensity = -1;
|
||||
int i = 0;
|
||||
for (; i < reportElements.size(); i++) {
|
||||
Object o = reportElements.get(i);
|
||||
if (TURB_WORDS.get(o) != null) {
|
||||
// We have turbulence of some type.
|
||||
turbulence = new Turbulence();
|
||||
reportElements.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i > 0) {
|
||||
while (i < reportElements.size()) {
|
||||
Object o = reportElements.get(i);
|
||||
// Check words that absolutely terminate search for turbulence.
|
||||
if (TURB_TERM_WORDS.contains(o)) {
|
||||
break;
|
||||
} else {
|
||||
if (i < reportElements.size()) {
|
||||
o = reportElements.get(i);
|
||||
Integer n = null;
|
||||
if ((n = TURB_FREQ.get(o)) != null) {
|
||||
turbulence.setFrequency(n);
|
||||
reportElements.remove(i);
|
||||
} else if ((n = TURB_TYPE.get(o)) != null) {
|
||||
turbulence.setType(n);
|
||||
reportElements.remove(i);
|
||||
} else if ((n = TURB_INT.get(o)) != null) {
|
||||
if (intensity < 0) {
|
||||
intensity = n;
|
||||
} else {
|
||||
if (n > intensity) {
|
||||
intensity = n;
|
||||
}
|
||||
}
|
||||
reportElements.remove(i);
|
||||
} else if ("NOT".equals(o)) {
|
||||
reportElements.remove(i);
|
||||
if (i < reportElements.size()) {
|
||||
if ("REPORTED".equals(reportElements.get(i))) {
|
||||
reportElements.remove(i);
|
||||
intensity = TURB_INT.get("NEG");
|
||||
}
|
||||
}
|
||||
} else if ("CODE".equals(o)) {
|
||||
reportElements.remove(i);
|
||||
} else {
|
||||
// Check to see if we have a turbulence range. In these cases if
|
||||
// more than one turbulence is found, report the most severe.
|
||||
if (o instanceof String) {
|
||||
String s = (String) o;
|
||||
// Two possible turbulence ranges we may have to work with.
|
||||
Integer turbA = null;
|
||||
Integer turbB = null;
|
||||
if (s.length() > 3) {
|
||||
if ((turbA = TURB_INT.get(s.substring(0, 3))) != null) {
|
||||
int pos = 3;
|
||||
// so now start at position 3 and check for possible
|
||||
// matches.
|
||||
while (pos < s.length()) {
|
||||
if ((turbB = TURB_INT.get(s
|
||||
.substring(pos))) != null) {
|
||||
break;
|
||||
} else {
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (turbA != null) {
|
||||
if (turbB != null) {
|
||||
if (turbB > turbA) {
|
||||
intensity = turbB;
|
||||
} else {
|
||||
intensity = turbA;
|
||||
}
|
||||
} else {
|
||||
intensity = turbA;
|
||||
}
|
||||
} else {
|
||||
if (turbB != null) {
|
||||
intensity = turbB;
|
||||
}
|
||||
}
|
||||
if (intensity > -1) {
|
||||
reportElements.remove(i);
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (intensity > 0) {
|
||||
// Check if we found a frequency or type without
|
||||
// an intensity.
|
||||
if (intensity < 0x10) {
|
||||
// if so then set it to light
|
||||
intensity |= AirepRecord.TURB_LGT;
|
||||
}
|
||||
turbulence.setIntensity(intensity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to locate and decode the 3 digit hazards and weather group.
|
||||
*/
|
||||
private void decodeWeatherGroup() {
|
||||
for (int i = 0; i < theElements.size(); i++) {
|
||||
Object o = theElements.get(i);
|
||||
for (int i = 0; i < reportElements.size(); i++) {
|
||||
Object o = reportElements.get(i);
|
||||
if (o instanceof String) {
|
||||
String s = (String) o;
|
||||
if (s.length() == 3) {
|
||||
if (WX_GROUP.matcher(s).find()) {
|
||||
weatherGroup = new AIREPWeather(s);
|
||||
theElements.set(i, weatherGroup);
|
||||
reportElements.set(i, weatherGroup);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -445,15 +845,15 @@ public class AirepParser {
|
|||
private void decodeWinds() {
|
||||
// By now we should have found the flight level data.
|
||||
int i = 0;
|
||||
for (; i < theElements.size(); i++) {
|
||||
if (theElements.get(i) instanceof AircraftFlightLevel) {
|
||||
for (; i < reportElements.size(); i++) {
|
||||
if (reportElements.get(i) instanceof AircraftFlightLevel) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
} // for()
|
||||
|
||||
for (; i < theElements.size(); i++) {
|
||||
Object o = theElements.get(i);
|
||||
for (; i < reportElements.size(); i++) {
|
||||
Object o = reportElements.get(i);
|
||||
if (o instanceof String) {
|
||||
String s = (String) o;
|
||||
if (s != null) {
|
||||
|
@ -497,8 +897,8 @@ public class AirepParser {
|
|||
}
|
||||
windDirection = new Double(value).intValue(); // windDirection.fromDegree(value);
|
||||
|
||||
theElements.set(i, windDirection);
|
||||
theElements.add(i + 1, windSpeed);
|
||||
reportElements.set(i, windDirection);
|
||||
reportElements.add(i + 1, windSpeed);
|
||||
} catch (Exception nothing) {
|
||||
String msg = String.format(
|
||||
"Error decoding winds: [%s] [%s]", windSpd,
|
||||
|
@ -519,16 +919,16 @@ public class AirepParser {
|
|||
* token to the end of the data.
|
||||
*/
|
||||
private void decodeMID() {
|
||||
for (int i = 0; i < theElements.size(); i++) {
|
||||
Object o = theElements.get(i);
|
||||
for (int i = 0; i < reportElements.size(); i++) {
|
||||
Object o = reportElements.get(i);
|
||||
if (o instanceof String) {
|
||||
String s = (String) o;
|
||||
if ("MID".equals(s)) {
|
||||
AircraftRemarks remarks = new AircraftRemarks(s);
|
||||
for (i++; i < theElements.size();) {
|
||||
for (i++; i < reportElements.size();) {
|
||||
remarks.addRemarks(" ");
|
||||
remarks.addRemarks((String) theElements.get(i));
|
||||
theElements.remove(i);
|
||||
remarks.addRemarks((String) reportElements.get(i));
|
||||
reportElements.remove(i);
|
||||
}
|
||||
rptRemarks = remarks;
|
||||
}
|
||||
|
@ -544,21 +944,24 @@ public class AirepParser {
|
|||
private void collectRemarks() {
|
||||
boolean timeFound = false;
|
||||
int i = 0;
|
||||
for (; i < theElements.size(); i++) {
|
||||
Object o = theElements.get(i);
|
||||
for (; i < reportElements.size(); i++) {
|
||||
Object o = reportElements.get(i);
|
||||
if (timeFound = (o instanceof Calendar)) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
} // for
|
||||
if (timeFound) {
|
||||
StringBuffer remarksBuffer = new StringBuffer();
|
||||
for (; i < theElements.size(); i++) {
|
||||
Object o = theElements.get(i);
|
||||
// i is pointing to the next element to examine.
|
||||
for (; i < reportElements.size();) {
|
||||
Object o = reportElements.get(i);
|
||||
if (o instanceof String) {
|
||||
theElements.remove(i);
|
||||
i--;
|
||||
reportElements.remove(i);
|
||||
remarksBuffer.append(o);
|
||||
remarksBuffer.append(" ");
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
} // for
|
||||
if (remarksBuffer.length() > 0) {
|
||||
|
@ -651,6 +1054,15 @@ public class AirepParser {
|
|||
return temperature;
|
||||
} // getAirTemperature()
|
||||
|
||||
/**
|
||||
* Get the decoded turbulence data.
|
||||
*
|
||||
* @return The decoded turbulence.
|
||||
*/
|
||||
public Turbulence getTurbulence() {
|
||||
return turbulence;
|
||||
}
|
||||
|
||||
public AIREPWeather getWeatherGroup() {
|
||||
return weatherGroup;
|
||||
} // getWeatherGroup()
|
||||
|
@ -683,24 +1095,4 @@ public class AirepParser {
|
|||
return (rptRemarks != null) ? rptRemarks.toString() : "";
|
||||
} // getRemarks()
|
||||
|
||||
|
||||
public static void main(String [] args) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
sdf.setTimeZone(TimeZone.getTimeZone("ZULU"));
|
||||
|
||||
Calendar refTime = TimeTools.getBaseCalendar(2011, 12, 14);
|
||||
refTime.set(Calendar.HOUR_OF_DAY, 17);
|
||||
refTime.set(Calendar.MINUTE, 15);
|
||||
refTime.set(Calendar.SECOND, 00);
|
||||
refTime.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
String data = "ARP UAL121 4400N 05700W 1640 F390 MS00 000/099KT TB MOD SK CLEAR=";
|
||||
AirepParser p = new AirepParser(data,refTime);
|
||||
System.out.println(sdf.format(p.getObservationTime().getTime()));
|
||||
|
||||
data = "ARP UAL121 4400N 05700W 1840 F390 MS00 000/099KT TB MOD SK CLEAR=";
|
||||
p = new AirepParser(data,refTime);
|
||||
System.out.println(sdf.format(p.getObservationTime().getTime()));
|
||||
}
|
||||
|
||||
} // AirepParser
|
||||
|
|
|
@ -0,0 +1,287 @@
|
|||
/**
|
||||
* This software was developed and / or modified by Raytheon Company,
|
||||
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||
*
|
||||
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||
* This software product contains export-restricted data whose
|
||||
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||
* to non-U.S. persons whether in the United States or abroad requires
|
||||
* an export license or other authorization.
|
||||
*
|
||||
* Contractor Name: Raytheon Company
|
||||
* Contractor Address: 6825 Pine Street, Suite 340
|
||||
* Mail Stop B8
|
||||
* Omaha, NE 68106
|
||||
* 402.291.0100
|
||||
*
|
||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||
* further licensing information.
|
||||
**/
|
||||
package test.airep;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.raytheon.edex.plugin.airep.AirepSeparator;
|
||||
import com.raytheon.edex.plugin.airep.decoder.AirepParser;
|
||||
import com.raytheon.uf.common.dataplugin.airep.AirepRecord;
|
||||
import com.raytheon.uf.edex.decodertools.time.TimeTools;
|
||||
|
||||
/**
|
||||
* Various tests against the AirepParser. Extracted some from "mains" that held
|
||||
* test code.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Sep 7, 2012 jkorman Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author jkorman
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class TestAIREPParser {
|
||||
|
||||
public static final String WMO_CRCRLF = "\r\r\n";
|
||||
|
||||
public static final String WMO_LEAD = "\01";
|
||||
|
||||
public static final String WMO_TRAIL = WMO_CRCRLF + "\03";
|
||||
|
||||
public static final int TURB_BIT = 0x80;
|
||||
|
||||
@Test
|
||||
public void testAIREPSeparator() {
|
||||
|
||||
String data = WMO_LEAD + WMO_CRCRLF + "205" + WMO_CRCRLF + "UAPA01 KWBC 071554" +
|
||||
WMO_CRCRLF + "ARP DAL278 3336N 165E 1543 F320 MS40 110/010KT TB 1=" +
|
||||
WMO_CRCRLF + "ARP PAL110 12N 130E 1544 F370 MS48 090/025KT=" +
|
||||
WMO_CRCRLF + "ARP UAL595 3746N 08107W 1504 F370 MS46 294/058KT TB LGT RM B752 OV" +
|
||||
WMO_CRCRLF + " BKW=" + WMO_TRAIL;
|
||||
String report = null;
|
||||
AirepSeparator sep = AirepSeparator.separate(data.getBytes(), null);
|
||||
assertNotNull(sep);
|
||||
assertTrue(sep.hasNext());
|
||||
report = sep.next().report;
|
||||
assertEquals("ARP DAL278 3336N 165E 1543 F320 MS40 110/010KT TB 1",report);
|
||||
report = sep.next().report;
|
||||
assertEquals("ARP PAL110 12N 130E 1544 F370 MS48 090/025KT",report);
|
||||
report = sep.next().report;
|
||||
assertEquals("ARP UAL595 3746N 08107W 1504 F370 MS46 294/058KT TB LGT RM B752 OV\r BKW",report);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLockup() {
|
||||
|
||||
String data = WMO_LEAD + WMO_CRCRLF + "494" + WMO_CRCRLF + "UAUS31 KWBC 112254" +
|
||||
WMO_CRCRLF + "ARP UAL819 4626N 10618W 2248 F360 TB CONT LGT CHOP RM B752 OV" +
|
||||
WMO_CRCRLF + " MLS270015=" + WMO_TRAIL;
|
||||
|
||||
String report = null;
|
||||
AirepSeparator sep = AirepSeparator.separate(data.getBytes(), null);
|
||||
assertNotNull(sep);
|
||||
assertTrue(sep.hasNext());
|
||||
AirepParser p = null;
|
||||
Calendar c = TimeTools.getSystemCalendar(2012, 9, 10, 16, 10);
|
||||
// The following are in degrees minutes
|
||||
p = new AirepParser(sep.next().report, c);
|
||||
assertNotNull(p);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Various forms of location identification.
|
||||
*/
|
||||
@Test
|
||||
public void testPositionDecode() {
|
||||
AirepParser p = null;
|
||||
Calendar c = TimeTools.getSystemCalendar(2012, 9, 10, 16, 10);
|
||||
// The following are in degrees minutes
|
||||
p = new AirepParser("ARP DAL278 3336N 165E 1543 F320 MS40 110/010KT TB LGT=", c);
|
||||
assertEquals("DAL278", p.getAircraftId());
|
||||
assertEquals(33.6, p.getLatitude(), 0.01);
|
||||
assertEquals(165.0, p.getLongitude(), 0.01);
|
||||
|
||||
p = new AirepParser("ARP DAL278 3336N 165W 1543 F320 MS40 110/010KT TB LGT=", c);
|
||||
assertEquals("DAL278", p.getAircraftId());
|
||||
assertEquals(33.6, p.getLatitude(), 0.01);
|
||||
assertEquals(-165.0, p.getLongitude(), 0.01);
|
||||
|
||||
p = new AirepParser("ARP DAL278 N3336 E165 1543 F320 MS40 110/010KT TB LGT=", c);
|
||||
assertEquals("DAL278", p.getAircraftId());
|
||||
assertEquals(33.6, p.getLatitude(), 0.01);
|
||||
assertEquals(165.0, p.getLongitude(), 0.01);
|
||||
|
||||
p = new AirepParser("ARP DAL278 N3336 W165 1543 F320 MS40 110/010KT TB LGT=", c);
|
||||
assertEquals("DAL278", p.getAircraftId());
|
||||
assertEquals(33.6, p.getLatitude(), 0.01);
|
||||
assertEquals(-165.0, p.getLongitude(), 0.01);
|
||||
|
||||
// These are in decimal degrees!
|
||||
p = new AirepParser("ARP DAL278 N33.36W089.25 1543 F320 MS40 110/010KT TB LGT=", c);
|
||||
assertEquals("DAL278", p.getAircraftId());
|
||||
assertEquals(33.36, p.getLatitude(), 0.01);
|
||||
assertEquals(-89.25, p.getLongitude(), 0.01);
|
||||
|
||||
p = new AirepParser("ARP DAL278 33.36N089.25W 1543 F320 MS40 110/010KT TB LGT=", c);
|
||||
assertEquals("DAL278", p.getAircraftId());
|
||||
assertEquals(33.36, p.getLatitude(), 0.01);
|
||||
assertEquals(-89.25, p.getLongitude(), 0.01);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test various turbulence decoding.
|
||||
*/
|
||||
@Test
|
||||
public void testAIREPParser() {
|
||||
|
||||
Calendar c = TimeTools.getSystemCalendar(2012, 9, 10, 16, 10);
|
||||
|
||||
AirepParser p = new AirepParser("ARP DAL278 3336N 165E 1543 F320 MS40 110/010KT TB LGT=", c);
|
||||
|
||||
AirepParser.Turbulence t = p.getTurbulence();
|
||||
assertNotNull(t);
|
||||
assertEquals(0x80 | AirepRecord.TURB_LGT, t.getTurbulence());
|
||||
|
||||
p = new AirepParser("ARP DAL278 3336N 165E 1543 F320 MS40 110/010KT TB MOD=", c);
|
||||
t = p.getTurbulence();
|
||||
assertNotNull(t);
|
||||
assertEquals(TURB_BIT | AirepRecord.TURB_MOD, t.getTurbulence());
|
||||
|
||||
p = new AirepParser("ARP DAL278 3336N 165E 1543 F320 MS40 110/010KT TB MDT=", c);
|
||||
t = p.getTurbulence();
|
||||
assertNotNull(t);
|
||||
assertEquals(0x40 | TURB_BIT, t.getTurbulence());
|
||||
|
||||
p = new AirepParser("ARP DAL278 3336N 165E 1543 F320 MS40 110/010KT TB LGT OCN MDT CAT=", c);
|
||||
t = p.getTurbulence();
|
||||
assertNotNull(t);
|
||||
assertEquals(TURB_BIT | AirepRecord.TURB_MOD | AirepRecord.TURB_TYPE_CAT | AirepRecord.TURB_FREQ_OCN, t.getTurbulence());
|
||||
|
||||
p = new AirepParser("ARP DAL278 3336N 165E 1543 F320 MS40 110/010KT TB LGT CAT OCN MDT=", c);
|
||||
t = p.getTurbulence();
|
||||
assertNotNull(t);
|
||||
assertEquals(TURB_BIT | AirepRecord.TURB_MOD | AirepRecord.TURB_TYPE_CAT | AirepRecord.TURB_FREQ_OCN, t.getTurbulence());
|
||||
|
||||
p = new AirepParser("ARP DAL278 3336N 165E 1543 F320 MS40 110/010KT TB SVR=", c);
|
||||
t = p.getTurbulence();
|
||||
assertNotNull(t);
|
||||
assertEquals(TURB_BIT | AirepRecord.TURB_SEV, t.getTurbulence());
|
||||
|
||||
p = new AirepParser("ARP DAL278 3336N 165E 1543 F320 MS40 110/010KT TB XTRM=", c);
|
||||
t = p.getTurbulence();
|
||||
assertNotNull(t);
|
||||
assertEquals(TURB_BIT | AirepRecord.TURB_XTRM, t.getTurbulence());
|
||||
|
||||
p = new AirepParser("ARP HAL4 2714N 14713W 0957 F350 MS46 270/052KT TB 1=", c);
|
||||
t = p.getTurbulence();
|
||||
assertNotNull(t);
|
||||
assertEquals(TURB_BIT | AirepRecord.TURB_LGT, t.getTurbulence());
|
||||
|
||||
// Compound turbulence value
|
||||
p = new AirepParser("ARP UAL761 3825N 11042W 1557 F340 MS44 235/030KT TB LGT-MOD RM\r\r\n A320 OV HVE=", c);
|
||||
t = p.getTurbulence();
|
||||
assertNotNull(t);
|
||||
assertEquals(TURB_BIT | AirepRecord.TURB_LGT_MOD, t.getTurbulence());
|
||||
// Compound turbulence value
|
||||
p = new AirepParser("ARP UAL761 3825N 11042W 1557 F340 MS44 235/030KT TB LGTMOD RM\r\r\n A320 OV HVE=", c);
|
||||
t = p.getTurbulence();
|
||||
assertNotNull(t);
|
||||
assertEquals(TURB_BIT | AirepRecord.TURB_LGT_MOD, t.getTurbulence());
|
||||
|
||||
// Two adjacent intensities-assume the strongest!
|
||||
p = new AirepParser("ARP UAL761 3825N 11042W 1557 F340 MS44 235/030KT TB LGT MOD RM\r\r\n A320 OV HVE=", c);
|
||||
t = p.getTurbulence();
|
||||
assertNotNull(t);
|
||||
assertEquals(TURB_BIT | AirepRecord.TURB_MOD, t.getTurbulence());
|
||||
// Checks that the intensity and frequency is extracted from non-reported data.
|
||||
p = new AirepParser("ARP UAL761 3825N 11042W 1557 F340 TB OCNL MOD TURBC IN CLOUD TOPS\r\r\n RM A320 OV HVE=", c);
|
||||
t = p.getTurbulence();
|
||||
assertNotNull(t);
|
||||
assertEquals(TURB_BIT | AirepRecord.TURB_MOD | AirepRecord.TURB_FREQ_OCN, t.getTurbulence());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAIREPTimes() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
sdf.setTimeZone(TimeZone.getTimeZone("ZULU"));
|
||||
|
||||
Calendar refTime = TimeTools.getBaseCalendar(2011, 12, 14);
|
||||
refTime.set(Calendar.HOUR_OF_DAY, 17);
|
||||
refTime.set(Calendar.MINUTE, 15);
|
||||
refTime.set(Calendar.SECOND, 00);
|
||||
refTime.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
AirepParser p = new AirepParser("ARP UAL121 4400N 05700W 1640 F390 MS00 000/099KT TB MOD SK CLEAR=",refTime);
|
||||
Calendar c = p.getObservationTime();
|
||||
assertNotNull(c);
|
||||
assertEquals(14, c.get(Calendar.DAY_OF_MONTH));
|
||||
assertEquals(16, c.get(Calendar.HOUR_OF_DAY));
|
||||
assertEquals(40, c.get(Calendar.MINUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that an observation time greater than the reference time rolls
|
||||
* back to the previous day.
|
||||
*/
|
||||
@Test
|
||||
public void testAIREPDateRollback() {
|
||||
Calendar refTime = TimeTools.getBaseCalendar(2011, 12, 14);
|
||||
refTime.set(Calendar.HOUR_OF_DAY, 17);
|
||||
refTime.set(Calendar.MINUTE, 15);
|
||||
refTime.set(Calendar.SECOND, 00);
|
||||
refTime.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
String data = "ARP UAL121 4400N 05700W 1840 F390 MS00 000/099KT TB MOD SK CLEAR=";
|
||||
AirepParser p = new AirepParser(data,refTime);
|
||||
Calendar c = p.getObservationTime();
|
||||
assertNotNull(c);
|
||||
assertEquals(13, c.get(Calendar.DAY_OF_MONTH));
|
||||
assertEquals(18, c.get(Calendar.HOUR_OF_DAY));
|
||||
assertEquals(40, c.get(Calendar.MINUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test various reported winds
|
||||
*/
|
||||
@Test
|
||||
public void testAIREPWinds() {
|
||||
|
||||
Calendar c = TimeTools.getSystemCalendar(2012, 9, 10, 16, 10);
|
||||
AirepParser p = null;
|
||||
|
||||
// Winds with "KT"
|
||||
p = new AirepParser("ARP DAL278 3336N 165E 1543 F320 MS40 110/010KT TB LGT=", c);
|
||||
assertNotNull(p);
|
||||
assertEquals(110, p.getWindDirection());
|
||||
assertEquals(10, p.getWindSpeed());
|
||||
|
||||
// Winds with "KTS"
|
||||
p = new AirepParser("ARP DAL278 3336N 165E 1543 F320 MS40 265/010KTS TB LGT=", c);
|
||||
assertNotNull(p);
|
||||
assertEquals(265, p.getWindDirection());
|
||||
assertEquals(10, p.getWindSpeed());
|
||||
|
||||
// Winds with no units - assume knots
|
||||
p = new AirepParser("ARP DAL278 3336N 165E 1543 F320 MS40 265/010 TB LGT=", c);
|
||||
assertNotNull(p);
|
||||
assertEquals(265, p.getWindDirection());
|
||||
assertEquals(10, p.getWindSpeed());
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -55,6 +55,10 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader;
|
|||
* ------------ ---------- ----------- --------------------------
|
||||
* 20080103 384 jkorman Initial Coding.
|
||||
* 20080219 861 jkorman Clean up javadoc.
|
||||
* ======================================
|
||||
* AWIPS2 DR Work
|
||||
* 20120911 1011 jkorman Changed to handle end of report
|
||||
* properly.
|
||||
* </pre>
|
||||
*
|
||||
* @author jkorman
|
||||
|
@ -66,6 +70,10 @@ public class PirepSeparator extends AbstractRecordSeparator {
|
|||
|
||||
private static final String PIREP_HDR = "[\\r\\n]*.*(UA|UUA) +/OV";
|
||||
|
||||
private static final String EOR_E = "=";
|
||||
|
||||
private static final String EOR_S = ";";
|
||||
|
||||
private WMOHeader wmoHeader = null;
|
||||
|
||||
private byte[] messageData = null;
|
||||
|
@ -183,6 +191,9 @@ public class PirepSeparator extends AbstractRecordSeparator {
|
|||
} else {
|
||||
observation = message.substring(bodyRecords.get(i)).trim();
|
||||
}
|
||||
if(observation.endsWith(EOR_E) || observation.endsWith(EOR_S)) {
|
||||
observation = observation.substring(0, observation.length() - 1);
|
||||
}
|
||||
reports.add(observation);
|
||||
}
|
||||
bodyRecords = null;
|
||||
|
|
|
@ -24,6 +24,8 @@ import java.util.List;
|
|||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import com.raytheon.edex.plugin.pirep.PirepSeparator;
|
||||
import com.raytheon.edex.plugin.pirep.decoder.PirepTools;
|
||||
import com.raytheon.edex.plugin.pirep.decoder.TEI;
|
||||
import com.raytheon.edex.plugin.pirep.decoder.TEIInfo;
|
||||
|
||||
|
@ -115,4 +117,26 @@ public class TestTEIInfo {
|
|||
assertEquals(TEI.WV, parts.get(6).getTei());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that "/SKC" does not get confused with the "/SK" TEI.
|
||||
*/
|
||||
@Test
|
||||
public void testNoTurbDecode() {
|
||||
final String data = "UBUS01 KMSC 061800\nCAO UA /OV DHT310017 /TM 1850 /FL125 /TP BE35 /WX FV30SM /TA 12\n/WV 24021KT /TB NEG=";
|
||||
|
||||
PirepSeparator sep = PirepSeparator.separate(data.getBytes(), null);
|
||||
while(sep.hasNext()) {
|
||||
List<TEIInfo> parts = TEIInfo.findTEIs(sep.next().getReport());
|
||||
PirepTools tools = null;
|
||||
for(TEIInfo info : parts) {
|
||||
System.out.println(info.getTeiText());
|
||||
if(TEI.TB.equals(info.getTei())) {
|
||||
tools = new PirepTools(info.getTeiText());
|
||||
System.out.println(tools.decodeTurbulenceData());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -68,6 +68,10 @@ import com.vividsolutions.jts.geom.Geometry;
|
|||
* 20080107 720 jkorman remove default assignments from attributes.
|
||||
* 20120405 435 dgilling Prevent NullPointerExceptions in
|
||||
* buildMessageData().
|
||||
* ======================================
|
||||
* AWIPS2 DR Work
|
||||
* 20120911 1011 jkorman Added ability to report turbulence from decoded
|
||||
* TB group.
|
||||
* </pre>
|
||||
*
|
||||
* @author jkorman
|
||||
|
@ -98,6 +102,34 @@ public class AirepRecord extends PluginDataObject implements ISpatialEnabled,
|
|||
|
||||
private static final HashMap<String, String> PARM_MAP = new HashMap<String, String>();
|
||||
|
||||
public static final int TURB_TYPE_CAT = 0x4;
|
||||
|
||||
public static final int TURB_TYPE_CHOP = 0x8;
|
||||
|
||||
public static final int TURB_TYPE_LLWS = 0xC;
|
||||
|
||||
public static final int TURB_FREQ_OCN = 0x1;
|
||||
|
||||
public static final int TURB_FREQ_INT = 0x2;
|
||||
|
||||
public static final int TURB_FREQ_CON = 0x3;
|
||||
|
||||
public static final int TURB_NEG = 0x00;
|
||||
|
||||
public static final int TURB_NEG_LGT = 0x10;
|
||||
|
||||
public static final int TURB_LGT = 0x20;
|
||||
|
||||
public static final int TURB_LGT_MOD = 0x30;
|
||||
|
||||
public static final int TURB_MOD = 0x40;
|
||||
|
||||
public static final int TURB_MOD_SEV = 0x50;
|
||||
|
||||
public static final int TURB_SEV = 0x60;
|
||||
|
||||
public static final int TURB_XTRM = 0x70;
|
||||
|
||||
// private static final HashMap<Integer, String> WX_MAP = new
|
||||
// HashMap<Integer, String>();
|
||||
|
||||
|
@ -121,6 +153,18 @@ public class AirepRecord extends PluginDataObject implements ISpatialEnabled,
|
|||
// WX_MAP.put(9, "TSRA");
|
||||
}
|
||||
|
||||
private static final HashMap<String, Integer> TURB_MAP = new HashMap<String, Integer>();
|
||||
static {
|
||||
TURB_MAP.put("NEG", new Integer(TURB_NEG));
|
||||
TURB_MAP.put("SMOOTHLGT", new Integer(TURB_NEG_LGT));
|
||||
TURB_MAP.put("LGT", new Integer(TURB_LGT));
|
||||
TURB_MAP.put("LGTMOD", new Integer(TURB_LGT_MOD));
|
||||
TURB_MAP.put("MOD", new Integer(TURB_MOD));
|
||||
TURB_MAP.put("MODSEV", new Integer(TURB_MOD_SEV));
|
||||
TURB_MAP.put("SEV", new Integer(TURB_SEV));
|
||||
TURB_MAP.put("EXTRM", new Integer(TURB_XTRM));
|
||||
}
|
||||
|
||||
@Column
|
||||
@DynamicSerializeElement
|
||||
@XmlAttribute
|
||||
|
@ -550,13 +594,89 @@ public class AirepRecord extends PluginDataObject implements ISpatialEnabled,
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the String representation of various AIREP parameters.
|
||||
*
|
||||
* @param The
|
||||
* parameter value to get.
|
||||
* @return A String array representing the value. A null reference may be
|
||||
* returned if the parameter does not exist or cannot be
|
||||
* represented.
|
||||
*/
|
||||
@Override
|
||||
public String[] getStrings(String paramName) {
|
||||
String[] retValue = null;
|
||||
String value = null;
|
||||
|
||||
if ("FLT_HZD".matches(paramName) && flightHazard != null) {
|
||||
String[] flightHazards = { flightHazard.toString() };
|
||||
return flightHazards;
|
||||
if (flightHazard != null) {
|
||||
retValue = new String[] { flightHazard.toString() };
|
||||
}
|
||||
} else if ("TBI".matches(paramName) && (flightConditions != null)) {
|
||||
int turb = flightConditions >> 4;
|
||||
// Is there turbulence to decode?
|
||||
if ((turb & 0x80) > 0) {
|
||||
// get the intensity
|
||||
switch (turb & 0x70) {
|
||||
case TURB_NEG: {
|
||||
value = "NEG";
|
||||
break;
|
||||
}
|
||||
case TURB_NEG_LGT: {
|
||||
value = "SMOOTHLGT";
|
||||
break;
|
||||
}
|
||||
case TURB_LGT: {
|
||||
value = "LGT";
|
||||
break;
|
||||
}
|
||||
case TURB_LGT_MOD: {
|
||||
value = "LGTMOD";
|
||||
break;
|
||||
}
|
||||
case TURB_MOD: {
|
||||
value = "MOD";
|
||||
break;
|
||||
}
|
||||
case TURB_MOD_SEV: {
|
||||
value = "MODSEV";
|
||||
break;
|
||||
}
|
||||
case TURB_SEV: {
|
||||
value = "SEV";
|
||||
break;
|
||||
}
|
||||
case TURB_XTRM: {
|
||||
value = "EXTRM";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ("TBF".matches(paramName) && (flightConditions != null)) {
|
||||
int turb = flightConditions >> 4;
|
||||
// Is there turbulence to decode?
|
||||
if ((turb & 0x80) > 0) {
|
||||
// get the intensity
|
||||
switch (turb & 0x03) {
|
||||
case TURB_FREQ_OCN: {
|
||||
value = "OCN";
|
||||
break;
|
||||
}
|
||||
case TURB_FREQ_INT: {
|
||||
value = "INT";
|
||||
break;
|
||||
}
|
||||
case TURB_FREQ_CON: {
|
||||
value = "CON";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
if (value != null) {
|
||||
retValue = new String[] { value };
|
||||
}
|
||||
return retValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -622,8 +742,41 @@ public class AirepRecord extends PluginDataObject implements ISpatialEnabled,
|
|||
messageData.append(windSpeed.intValue());
|
||||
messageData.append("KT");
|
||||
}
|
||||
messageData.append("TB");
|
||||
|
||||
if(flightConditions != null) {
|
||||
int turb = flightConditions >> 4;
|
||||
if ((turb & 0x80) > 0) {
|
||||
messageData.append(" TB");
|
||||
String[] data = getStrings("TBF");
|
||||
if ((data != null) && (data.length == 1)) {
|
||||
messageData.append(" ");
|
||||
messageData.append(data[0]);
|
||||
}
|
||||
data = getStrings("TBI");
|
||||
if ((data != null) && (data.length == 1)) {
|
||||
messageData.append(" ");
|
||||
messageData.append(data[0]);
|
||||
}
|
||||
String type = null;
|
||||
switch (turb & 0xC) {
|
||||
case TURB_TYPE_CAT: {
|
||||
type = "CAT";
|
||||
break;
|
||||
}
|
||||
case TURB_TYPE_CHOP: {
|
||||
type = "CHOP";
|
||||
break;
|
||||
}
|
||||
case TURB_TYPE_LLWS: {
|
||||
type = "LLWS";
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (type != null) {
|
||||
messageData.append(" ");
|
||||
messageData.append(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
return messageData.toString();
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue