VLab Issue #18075 - DR 18336 fix. All keep-alives were being treated as NLDN. Get source from WMO header instead; fixes #18075
Change-Id: I53a392780148de85de9c25fff05c313737137b57 Former-commit-id: 3cf025add9b0c2636a442784bb977601ed7b434e
This commit is contained in:
parent
c4e85ee05d
commit
de50a8ac01
3 changed files with 98 additions and 41 deletions
|
@ -101,6 +101,7 @@ import com.raytheon.uf.edex.decodertools.core.DecoderTools;
|
||||||
* Aug 04, 2014 3488 bclement added checkBinRange(), rebin() and finalizeRecords()
|
* Aug 04, 2014 3488 bclement added checkBinRange(), rebin() and finalizeRecords()
|
||||||
* Mar 08, 2016 18336 amoore Keep-alive messages should update the legend.
|
* Mar 08, 2016 18336 amoore Keep-alive messages should update the legend.
|
||||||
* Apr 07, 2016 DR18763 mgamazaychikov Switched to using LightningWMOHeader.
|
* Apr 07, 2016 DR18763 mgamazaychikov Switched to using LightningWMOHeader.
|
||||||
|
* May 02, 2016 18336 amoore BinLightningRecord constructor takes source.
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -205,7 +206,6 @@ public class BinLightningDecoder {
|
||||||
* and added logic to process both encrypted data and legacy
|
* and added logic to process both encrypted data and legacy
|
||||||
* data
|
* data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Collection<LightningStrikePoint> strikes = decodeBinLightningData(
|
Collection<LightningStrikePoint> strikes = decodeBinLightningData(
|
||||||
data, pdata, traceId, wmoHdr, baseTime.getTime());
|
data, pdata, traceId, wmoHdr, baseTime.getTime());
|
||||||
|
|
||||||
|
@ -213,17 +213,23 @@ public class BinLightningDecoder {
|
||||||
* Done MOD by Wufeng Zhou
|
* Done MOD by Wufeng Zhou
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// post processing data - if not keep-alive record
|
// post processing data
|
||||||
BinLightningRecord report = null;
|
BinLightningRecord report = null;
|
||||||
if (strikes.size() > 0) {
|
if (strikes.size() > 0) {
|
||||||
|
// not a keep-alive
|
||||||
report = LightningGeoFilter.createFilteredRecord(strikes);
|
report = LightningGeoFilter.createFilteredRecord(strikes);
|
||||||
} else {
|
} else {
|
||||||
|
// keep-alive, get the source from WMO header
|
||||||
|
String source = getSourceFromHeader(wmoHdr);
|
||||||
|
|
||||||
synchronized (SDF) {
|
synchronized (SDF) {
|
||||||
logger.info(traceId
|
logger.info(traceId
|
||||||
+ ": found keep-alive record of base time ["
|
+ ": found keep-alive record of base time ["
|
||||||
+ SDF.format(baseTime.getTime()) + "]");
|
+ SDF.format(baseTime.getTime())
|
||||||
|
+ "] and source [" + source + "]");
|
||||||
}
|
}
|
||||||
report = new BinLightningRecord(baseTime);
|
|
||||||
|
report = new BinLightningRecord(baseTime, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection<BinLightningRecord> records = checkBinRange(report,
|
Collection<BinLightningRecord> records = checkBinRange(report,
|
||||||
|
@ -395,8 +401,8 @@ public class BinLightningDecoder {
|
||||||
* LightningStrikePoint
|
* LightningStrikePoint
|
||||||
*/
|
*/
|
||||||
public static List<LightningStrikePoint> decodeBinLightningData(
|
public static List<LightningStrikePoint> decodeBinLightningData(
|
||||||
byte[] data, byte[] pdata, String traceId, LightningWMOHeader wmoHdr,
|
byte[] data, byte[] pdata, String traceId,
|
||||||
Date dataDate) {
|
LightningWMOHeader wmoHdr, Date dataDate) {
|
||||||
if (pdata == null) { // if data without header not passed, we'll strip
|
if (pdata == null) { // if data without header not passed, we'll strip
|
||||||
// the WMO header here
|
// the WMO header here
|
||||||
LightningWMOHeader header = new LightningWMOHeader(data);
|
LightningWMOHeader header = new LightningWMOHeader(data);
|
||||||
|
@ -481,8 +487,8 @@ public class BinLightningDecoder {
|
||||||
return new ArrayList<>(0);
|
return new ArrayList<>(0);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* not keep-alive record, then check data validity and decode
|
* not necessarily keep-alive record, then check data validity
|
||||||
* into an ArrayList<LightningStrikePoint> of strikes
|
* and decode into an ArrayList<LightningStrikePoint> of strikes
|
||||||
*/
|
*/
|
||||||
if (BinLightningDecoderUtil
|
if (BinLightningDecoderUtil
|
||||||
.isLightningDataRecords(decryptedData)) {
|
.isLightningDataRecords(decryptedData)) {
|
||||||
|
@ -563,24 +569,9 @@ public class BinLightningDecoder {
|
||||||
switch (decoder.getError()) {
|
switch (decoder.getError()) {
|
||||||
case IBinLightningDecoder.NO_ERROR: {
|
case IBinLightningDecoder.NO_ERROR: {
|
||||||
for (LightningStrikePoint strike : decoder) {
|
for (LightningStrikePoint strike : decoder) {
|
||||||
/*
|
String source = getSourceFromHeader(wmoHdr);
|
||||||
* use WMO Header to distinguish NLDN or GLD360 data because
|
|
||||||
* no bit-shifted data spec available for GLD360.
|
strike.setLightSource(source);
|
||||||
* 12/24/2013, WZ The WMO header start string is defined in
|
|
||||||
* BinLightningAESKey.properties file (normally, GLD360 data
|
|
||||||
* will have WMO header starts with SFPA41, or SFPA99 for
|
|
||||||
* test data.)
|
|
||||||
*/
|
|
||||||
String gld360WMOHeaderString = BinLightningAESKey
|
|
||||||
.getProps().getProperty(
|
|
||||||
"binlightning.gld360WMOHeaderStartString",
|
|
||||||
"");
|
|
||||||
if (gld360WMOHeaderString.trim().equals("") == false
|
|
||||||
&& wmoHdr.getWmoHeader().startsWith(
|
|
||||||
gld360WMOHeaderString)) {
|
|
||||||
// GLD360 data based on the setup
|
|
||||||
strike.setLightSource("GLD");
|
|
||||||
}
|
|
||||||
strikes.add(strike);
|
strikes.add(strike);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -593,6 +584,45 @@ public class BinLightningDecoder {
|
||||||
return strikes;
|
return strikes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the data source from the given WMO header.
|
||||||
|
*
|
||||||
|
* @param wmoHdr
|
||||||
|
* the header.
|
||||||
|
* @return the data source according to text from the header.
|
||||||
|
*/
|
||||||
|
private static String getSourceFromHeader(LightningWMOHeader wmoHdr) {
|
||||||
|
/*
|
||||||
|
* use WMO Header to distinguish NLDN or GLD360 data because no
|
||||||
|
* bit-shifted data spec available for GLD360. 12/24/2013, WZ The WMO
|
||||||
|
* header start string is defined in BinLightningAESKey.properties file
|
||||||
|
* (normally, GLD360 data will have WMO header starts with SFPA41, or
|
||||||
|
* SFPA99 for test data.)
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* continually get the properties locally instead of as a constant
|
||||||
|
* because the properties file could be changed and reloaded by the
|
||||||
|
* user.
|
||||||
|
*/
|
||||||
|
String gld360WMOHeaderString = BinLightningAESKey.getProps()
|
||||||
|
.getProperty("binlightning.gld360WMOHeaderStartString", "");
|
||||||
|
|
||||||
|
String source = null;
|
||||||
|
|
||||||
|
if (gld360WMOHeaderString.trim().equals("") == false
|
||||||
|
&& wmoHdr.getWmoHeader().startsWith(gld360WMOHeaderString)) {
|
||||||
|
// GLD360 data based on the setup
|
||||||
|
source = "GLD";
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* default source is NLDN, which is the only other option at this time
|
||||||
|
* for this decoder (5/2/2016, DR 18336). For future sources, add here
|
||||||
|
* and modify BinLightningAESKey.properties.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return BinLightningRecord.validateSource(source);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a trace identifier for the source data.
|
* Set a trace identifier for the source data.
|
||||||
*
|
*
|
||||||
|
|
|
@ -62,6 +62,7 @@ import com.raytheon.uf.common.wmo.WMOTimeParser;
|
||||||
* Jun 19, 2014 3226 bclement added validator callback
|
* Jun 19, 2014 3226 bclement added validator callback
|
||||||
* Jul 07, 2015 4581 skorolev Corrected decodeStrikes to avoid BufferUnderflowException.
|
* Jul 07, 2015 4581 skorolev Corrected decodeStrikes to avoid BufferUnderflowException.
|
||||||
* Apr 07, 2016 DR18763 mgamazaychikov Switched to using LightningWMOHeader.
|
* Apr 07, 2016 DR18763 mgamazaychikov Switched to using LightningWMOHeader.
|
||||||
|
* May 02, 2016 18336 amoore Keep-alive messages should update the legend.
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -205,13 +206,17 @@ public class TotalLightningDecoder {
|
||||||
pdata = decrypt(wmoHdr, fileName, pdata);
|
pdata = decrypt(wmoHdr, fileName, pdata);
|
||||||
}
|
}
|
||||||
List<LightningStrikePoint> strikes = decodeStrikes(fileName, pdata);
|
List<LightningStrikePoint> strikes = decodeStrikes(fileName, pdata);
|
||||||
|
|
||||||
|
BinLightningRecord record;
|
||||||
if (!strikes.isEmpty()) {
|
if (!strikes.isEmpty()) {
|
||||||
BinLightningRecord record = LightningGeoFilter
|
record = LightningGeoFilter.createFilteredRecord(strikes);
|
||||||
.createFilteredRecord(strikes);
|
|
||||||
return new PluginDataObject[] { record };
|
|
||||||
} else {
|
} else {
|
||||||
return new PluginDataObject[0];
|
// keep-alive record
|
||||||
|
Calendar baseTime = WMOTimeParser.findDataTime(wmoHdr.getYYGGgg(),
|
||||||
|
fileName);
|
||||||
|
record = new BinLightningRecord(baseTime, DATA_SOURCE);
|
||||||
}
|
}
|
||||||
|
return new PluginDataObject[] { record };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -221,8 +226,8 @@ public class TotalLightningDecoder {
|
||||||
* @return
|
* @return
|
||||||
* @throws DecoderException
|
* @throws DecoderException
|
||||||
*/
|
*/
|
||||||
private byte[] decrypt(LightningWMOHeader wmoHdr, String fileName, byte[] pdata)
|
private byte[] decrypt(LightningWMOHeader wmoHdr, String fileName,
|
||||||
throws DecoderException {
|
byte[] pdata) throws DecoderException {
|
||||||
Calendar baseTime = WMOTimeParser.findDataTime(wmoHdr.getYYGGgg(),
|
Calendar baseTime = WMOTimeParser.findDataTime(wmoHdr.getYYGGgg(),
|
||||||
fileName);
|
fileName);
|
||||||
pdata = EncryptedBinLightningCipher.prepDataForDecryption(pdata,
|
pdata = EncryptedBinLightningCipher.prepDataForDecryption(pdata,
|
||||||
|
@ -236,11 +241,11 @@ public class TotalLightningDecoder {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract strike data from raw binary
|
* Extract strike data from raw binary, ignoring keep-alive strikes.
|
||||||
*
|
*
|
||||||
* @param fileName
|
* @param fileName
|
||||||
* @param pdata
|
* @param pdata
|
||||||
* @return
|
* @return list of lightning strike points, ignoring keep-alive strikes.
|
||||||
* @throws DecoderException
|
* @throws DecoderException
|
||||||
*/
|
*/
|
||||||
private List<LightningStrikePoint> decodeStrikes(String fileName,
|
private List<LightningStrikePoint> decodeStrikes(String fileName,
|
||||||
|
|
|
@ -94,6 +94,7 @@ import com.raytheon.uf.common.time.util.TimeUtil;
|
||||||
* Jan 22, 2014 3949 nabowle refactor out default and unknown source constants.
|
* Jan 22, 2014 3949 nabowle refactor out default and unknown source constants.
|
||||||
* Jul 23, 2015 2360 rferrel Add name to unique constraint.
|
* Jul 23, 2015 2360 rferrel Add name to unique constraint.
|
||||||
* Mar 08, 2016 18336 amoore Keep-alive messages should update the legend.
|
* Mar 08, 2016 18336 amoore Keep-alive messages should update the legend.
|
||||||
|
* May 02, 2016 18336 amoore BinLightningRecord constructor takes source.
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -172,9 +173,11 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
|
||||||
*
|
*
|
||||||
* @param dateTime
|
* @param dateTime
|
||||||
* WMO header base date.
|
* WMO header base date.
|
||||||
|
* @param vendorSource
|
||||||
|
* source of the record.
|
||||||
*/
|
*/
|
||||||
public BinLightningRecord(final Calendar dateTime) {
|
public BinLightningRecord(final Calendar dateTime, String vendorSource) {
|
||||||
source = LightningConstants.DEFAULT_SOURCE;
|
source = vendorSource;
|
||||||
|
|
||||||
// only data shall be datetime for keep-alive
|
// only data shall be datetime for keep-alive
|
||||||
strikeDataArrays.put(LightningConstants.TIME_DATASET,
|
strikeDataArrays.put(LightningConstants.TIME_DATASET,
|
||||||
|
@ -321,18 +324,37 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract data source from strike
|
* Extract data source from strike.
|
||||||
*
|
*
|
||||||
* @param strike
|
* @param strike
|
||||||
* @return
|
* the strike from which to get data source.
|
||||||
|
* @return the strike's data source. If null, return
|
||||||
|
* {@link LightningConstants#DEFAULT_SOURCE}. If empty, return
|
||||||
|
* {@link LightningConstants#UNKNOWN_SOURCE}.
|
||||||
*/
|
*/
|
||||||
public static String getDataSource(LightningStrikePoint strike) {
|
public static String getDataSource(LightningStrikePoint strike) {
|
||||||
if (strike.getLightSource() == null) {
|
return validateSource(strike.getLightSource());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Examine the lightning source given, and return a pre-defined constant if
|
||||||
|
* it is empty or null. Return lightning source as-is if non-null and
|
||||||
|
* non-empty.
|
||||||
|
*
|
||||||
|
* @param iSource
|
||||||
|
* the lightning source to examine.
|
||||||
|
* @return a validated lightning source. If null, return
|
||||||
|
* {@link LightningConstants#DEFAULT_SOURCE}. If empty, return
|
||||||
|
* {@link LightningConstants#UNKNOWN_SOURCE}. If neither, return the
|
||||||
|
* original input.
|
||||||
|
*/
|
||||||
|
public static String validateSource(String iSource) {
|
||||||
|
if (iSource == null) {
|
||||||
return LightningConstants.DEFAULT_SOURCE;
|
return LightningConstants.DEFAULT_SOURCE;
|
||||||
} else if (strike.getLightSource().isEmpty()) {
|
} else if (iSource.isEmpty()) {
|
||||||
return LightningConstants.UNKNOWN_SOURCE;
|
return LightningConstants.UNKNOWN_SOURCE;
|
||||||
} else {
|
} else {
|
||||||
return strike.getLightSource();
|
return iSource;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue