From de50a8ac016eadd5168d8a94731b2f68e94e19e3 Mon Sep 17 00:00:00 2001 From: Andrew Moore Date: Fri, 22 Apr 2016 16:03:57 +0000 Subject: [PATCH] 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 --- .../binlightning/BinLightningDecoder.java | 82 +++++++++++++------ .../total/TotalLightningDecoder.java | 21 +++-- .../binlightning/BinLightningRecord.java | 36 ++++++-- 3 files changed, 98 insertions(+), 41 deletions(-) diff --git a/edexOsgi/com.raytheon.edex.plugin.binlightning/src/com/raytheon/edex/plugin/binlightning/BinLightningDecoder.java b/edexOsgi/com.raytheon.edex.plugin.binlightning/src/com/raytheon/edex/plugin/binlightning/BinLightningDecoder.java index dd8ec4b9bd..0f365d26a5 100644 --- a/edexOsgi/com.raytheon.edex.plugin.binlightning/src/com/raytheon/edex/plugin/binlightning/BinLightningDecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.binlightning/src/com/raytheon/edex/plugin/binlightning/BinLightningDecoder.java @@ -101,6 +101,7 @@ import com.raytheon.uf.edex.decodertools.core.DecoderTools; * Aug 04, 2014 3488 bclement added checkBinRange(), rebin() and finalizeRecords() * Mar 08, 2016 18336 amoore Keep-alive messages should update the legend. * Apr 07, 2016 DR18763 mgamazaychikov Switched to using LightningWMOHeader. + * May 02, 2016 18336 amoore BinLightningRecord constructor takes source. * * * @@ -205,7 +206,6 @@ public class BinLightningDecoder { * and added logic to process both encrypted data and legacy * data */ - Collection strikes = decodeBinLightningData( data, pdata, traceId, wmoHdr, baseTime.getTime()); @@ -213,17 +213,23 @@ public class BinLightningDecoder { * Done MOD by Wufeng Zhou */ - // post processing data - if not keep-alive record + // post processing data BinLightningRecord report = null; if (strikes.size() > 0) { + // not a keep-alive report = LightningGeoFilter.createFilteredRecord(strikes); } else { + // keep-alive, get the source from WMO header + String source = getSourceFromHeader(wmoHdr); + synchronized (SDF) { logger.info(traceId + ": 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 records = checkBinRange(report, @@ -395,8 +401,8 @@ public class BinLightningDecoder { * LightningStrikePoint */ public static List decodeBinLightningData( - byte[] data, byte[] pdata, String traceId, LightningWMOHeader wmoHdr, - Date dataDate) { + byte[] data, byte[] pdata, String traceId, + LightningWMOHeader wmoHdr, Date dataDate) { if (pdata == null) { // if data without header not passed, we'll strip // the WMO header here LightningWMOHeader header = new LightningWMOHeader(data); @@ -481,8 +487,8 @@ public class BinLightningDecoder { return new ArrayList<>(0); } /* - * not keep-alive record, then check data validity and decode - * into an ArrayList of strikes + * not necessarily keep-alive record, then check data validity + * and decode into an ArrayList of strikes */ if (BinLightningDecoderUtil .isLightningDataRecords(decryptedData)) { @@ -563,24 +569,9 @@ public class BinLightningDecoder { switch (decoder.getError()) { case IBinLightningDecoder.NO_ERROR: { for (LightningStrikePoint strike : decoder) { - /* - * 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.) - */ - 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"); - } + String source = getSourceFromHeader(wmoHdr); + + strike.setLightSource(source); strikes.add(strike); } break; @@ -593,6 +584,45 @@ public class BinLightningDecoder { 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. * diff --git a/edexOsgi/com.raytheon.edex.plugin.binlightning/src/com/raytheon/edex/plugin/binlightning/total/TotalLightningDecoder.java b/edexOsgi/com.raytheon.edex.plugin.binlightning/src/com/raytheon/edex/plugin/binlightning/total/TotalLightningDecoder.java index 7b85cc9ec8..a953ae1a92 100644 --- a/edexOsgi/com.raytheon.edex.plugin.binlightning/src/com/raytheon/edex/plugin/binlightning/total/TotalLightningDecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.binlightning/src/com/raytheon/edex/plugin/binlightning/total/TotalLightningDecoder.java @@ -62,6 +62,7 @@ import com.raytheon.uf.common.wmo.WMOTimeParser; * Jun 19, 2014 3226 bclement added validator callback * Jul 07, 2015 4581 skorolev Corrected decodeStrikes to avoid BufferUnderflowException. * Apr 07, 2016 DR18763 mgamazaychikov Switched to using LightningWMOHeader. + * May 02, 2016 18336 amoore Keep-alive messages should update the legend. * * * @@ -205,13 +206,17 @@ public class TotalLightningDecoder { pdata = decrypt(wmoHdr, fileName, pdata); } List strikes = decodeStrikes(fileName, pdata); + + BinLightningRecord record; if (!strikes.isEmpty()) { - BinLightningRecord record = LightningGeoFilter - .createFilteredRecord(strikes); - return new PluginDataObject[] { record }; + record = LightningGeoFilter.createFilteredRecord(strikes); } 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 * @throws DecoderException */ - private byte[] decrypt(LightningWMOHeader wmoHdr, String fileName, byte[] pdata) - throws DecoderException { + private byte[] decrypt(LightningWMOHeader wmoHdr, String fileName, + byte[] pdata) throws DecoderException { Calendar baseTime = WMOTimeParser.findDataTime(wmoHdr.getYYGGgg(), fileName); 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 pdata - * @return + * @return list of lightning strike points, ignoring keep-alive strikes. * @throws DecoderException */ private List decodeStrikes(String fileName, diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.binlightning/src/com/raytheon/uf/common/dataplugin/binlightning/BinLightningRecord.java b/edexOsgi/com.raytheon.uf.common.dataplugin.binlightning/src/com/raytheon/uf/common/dataplugin/binlightning/BinLightningRecord.java index c848eed96f..5b40b04183 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.binlightning/src/com/raytheon/uf/common/dataplugin/binlightning/BinLightningRecord.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.binlightning/src/com/raytheon/uf/common/dataplugin/binlightning/BinLightningRecord.java @@ -94,6 +94,7 @@ import com.raytheon.uf.common.time.util.TimeUtil; * Jan 22, 2014 3949 nabowle refactor out default and unknown source constants. * Jul 23, 2015 2360 rferrel Add name to unique constraint. * Mar 08, 2016 18336 amoore Keep-alive messages should update the legend. + * May 02, 2016 18336 amoore BinLightningRecord constructor takes source. * * * @@ -172,9 +173,11 @@ public class BinLightningRecord extends PersistablePluginDataObject implements * * @param dateTime * WMO header base date. + * @param vendorSource + * source of the record. */ - public BinLightningRecord(final Calendar dateTime) { - source = LightningConstants.DEFAULT_SOURCE; + public BinLightningRecord(final Calendar dateTime, String vendorSource) { + source = vendorSource; // only data shall be datetime for keep-alive 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 - * @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) { - 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; - } else if (strike.getLightSource().isEmpty()) { + } else if (iSource.isEmpty()) { return LightningConstants.UNKNOWN_SOURCE; } else { - return strike.getLightSource(); + return iSource; } }