Issue #1011 - Corrected AIREP turbulence decoding

Change-Id: Ie56a2b916df7b68f28cca73235f33596b903c5b1

Former-commit-id: 6531df3ab0 [formerly c0e5570aa2] [formerly d3fd8a53df [formerly 41dd04864bbd4b510b5e1b0c6e4259bb140b9b2e]]
Former-commit-id: d3fd8a53df
Former-commit-id: 029f9537c8
This commit is contained in:
James Korman 2012-09-12 16:16:11 -05:00
parent b93815fefd
commit 2241841dcd
10 changed files with 1000 additions and 94 deletions

View file

@ -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

View file

@ -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>

View file

@ -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

View file

@ -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;

View file

@ -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");
}

View file

@ -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

View file

@ -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());
}
}

View file

@ -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;

View file

@ -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());
}
}
}
}
}

View file

@ -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();
}