Omaha #3226 added total lightning decoder
refactored binlightning to support pulse data renamed strikeCount dataset to pulseCount added initial cave support for total lightning Change-Id: I67f8a0f26a615ddefb9ff7f7d7d78bb05f0877f3 Former-commit-id:c278000764
[formerlyc278000764
[formerly e2583481a77d08249030838ebd52eed6e54b2986]] Former-commit-id:f39896b2d1
Former-commit-id:b98a3494fe
This commit is contained in:
parent
99f7f6da90
commit
ca1b869647
33 changed files with 1724 additions and 701 deletions
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<menuTemplate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<contribute xsi:type="bundleItem" file="bundles/LightningPlot60Min.xml"
|
||||
menuText="1hr CG flash plot" id="1HrLightningFlashPlot">
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/LightningPlot15Min.xml"
|
||||
menuText="15min CG flash plot" id="15MinLightningFlashPlot">
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/LightningPlot15MinPN.xml"
|
||||
menuText="15min Pos/Neg CG flash plot" id="15MinPNLightningFlashPlot">
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/LightningPlot5Min.xml"
|
||||
menuText="5min CG flash plot" id="5MinLightningFlashPlot">
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/LightningSeq.xml"
|
||||
menuText="1min Lgtng Seq CG flash" id="1MinLightningFlashSeq">
|
||||
</contribute>
|
||||
</menuTemplate>
|
|
@ -20,27 +20,18 @@
|
|||
-->
|
||||
<menuTemplate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<contribute xsi:type="bundleItem" file="bundles/LightningPlot60Min.xml"
|
||||
menuText="1hr CG stroke plot" id="1HrLightningStrokePlot"
|
||||
productInterval="3600">
|
||||
<dataURI>/binlightning/%</dataURI>
|
||||
menuText="1hr CG stroke plot" id="1HrLightningStrokePlot">
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/LightningPlot15Min.xml"
|
||||
menuText="15min CG stroke plot" id="15MinLightningStrokePlot"
|
||||
productInterval="900">
|
||||
<dataURI>/binlightning/%</dataURI>
|
||||
menuText="15min CG stroke plot" id="15MinLightningStrokePlot">
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/LightningPlot15MinPN.xml"
|
||||
menuText="15min Pos/Neg CG stroke plot" id="15MinPNLightningStrokePlot"
|
||||
productInterval="900">
|
||||
<dataURI>/binlightning/%</dataURI>
|
||||
menuText="15min Pos/Neg CG stroke plot" id="15MinPNLightningStrokePlot">
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/LightningPlot5Min.xml"
|
||||
menuText="5min CG stroke plot" id="5MinLightningStrokePlot"
|
||||
productInterval="300">
|
||||
<dataURI>/binlightning/%</dataURI>
|
||||
menuText="5min CG stroke plot" id="5MinLightningStrokePlot">
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/LightningSeq.xml"
|
||||
menuText="1min Lgtng Seq CG stroke" id="1MinLightningStrokeSeq">
|
||||
<dataURI>/binlightning/%</dataURI>
|
||||
</contribute>
|
||||
</menuTemplate>
|
|
@ -29,4 +29,9 @@
|
|||
<substitute key="source" value="GLD"/>
|
||||
</contribute>
|
||||
</contribute>
|
||||
<contribute xsi:type="subMenu" menuText="Total Lightning" id="ENTLNSubMenu">
|
||||
<contribute xsi:type="subinclude" fileName="menus/lightning/entlnLightningBundleItems.xml">
|
||||
<substitute key="source" value="ENTLN"/>
|
||||
</contribute>
|
||||
</contribute>
|
||||
</menuTemplate>
|
|
@ -20,27 +20,18 @@
|
|||
-->
|
||||
<menuTemplate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<contribute xsi:type="bundleItem" file="bundles/LightningPlot60Min.xml"
|
||||
menuText="1hr CG flash plot" id="1HrLightningFlashPlot"
|
||||
productInterval="3600">
|
||||
<dataURI>/binlightning/%</dataURI>
|
||||
menuText="1hr CG flash plot" id="1HrLightningFlashPlot">
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/LightningPlot15Min.xml"
|
||||
menuText="15min CG flash plot" id="15MinLightningFlashPlot"
|
||||
productInterval="900">
|
||||
<dataURI>/binlightning/%</dataURI>
|
||||
menuText="15min CG flash plot" id="15MinLightningFlashPlot">
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/LightningPlot15MinPN.xml"
|
||||
menuText="15min Pos/Neg CG flash plot" id="15MinPNLightningFlashPlot"
|
||||
productInterval="900">
|
||||
<dataURI>/binlightning/%</dataURI>
|
||||
menuText="15min Pos/Neg CG flash plot" id="15MinPNLightningFlashPlot">
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/LightningPlot5Min.xml"
|
||||
menuText="5min CG flash plot" id="5MinLightningFlashPlot"
|
||||
productInterval="300">
|
||||
<dataURI>/binlightning/%</dataURI>
|
||||
menuText="5min CG flash plot" id="5MinLightningFlashPlot">
|
||||
</contribute>
|
||||
<contribute xsi:type="bundleItem" file="bundles/LightningSeq.xml"
|
||||
menuText="1min Lgtng Seq CG flash" id="1MinLightningFlashSeq">
|
||||
<dataURI>/binlightning/%</dataURI>
|
||||
</contribute>
|
||||
</menuTemplate>
|
|
@ -35,6 +35,7 @@ import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
|||
import com.raytheon.uf.common.dataplugin.HDF5Util;
|
||||
import com.raytheon.uf.common.dataplugin.PluginDataObject;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.BinLightningRecord;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.LightningConstants;
|
||||
import com.raytheon.uf.common.datastorage.DataStoreFactory;
|
||||
import com.raytheon.uf.common.datastorage.IDataStore;
|
||||
import com.raytheon.uf.common.datastorage.Request;
|
||||
|
@ -94,6 +95,7 @@ import com.raytheon.uf.viz.core.rsc.capabilities.MagnificationCapability;
|
|||
* fields when magnification set to 0
|
||||
* Feb 27, 2013 DCS 152 jgerth/elau Support for WWLLN and multiple sources
|
||||
* Jan 21, 2014 2667 bclement renamed record's lightSource field to source
|
||||
* Jun 05, 2014 3226 bclement reference datarecords by LightningConstants
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -637,7 +639,15 @@ public class LightningResource extends
|
|||
recordList.add(rec);
|
||||
}
|
||||
|
||||
List<IDataRecord> times = recordMap.get("obsTime");
|
||||
List<IDataRecord> times = recordMap
|
||||
.get(LightningConstants.TIME_DATASET);
|
||||
|
||||
List<IDataRecord> intensities = recordMap
|
||||
.get(LightningConstants.INTENSITY_DATASET);
|
||||
List<IDataRecord> lats = recordMap
|
||||
.get(LightningConstants.LAT_DATASET);
|
||||
List<IDataRecord> lons = recordMap
|
||||
.get(LightningConstants.LON_DATASET);
|
||||
|
||||
int k = 0;
|
||||
for (IDataRecord timeRec : times) {
|
||||
|
@ -647,12 +657,13 @@ public class LightningResource extends
|
|||
int numRecords = (int) time.getSizes()[0];
|
||||
|
||||
long[] timeData = time.getLongData();
|
||||
int[] intensityData = ((IntegerDataRecord) recordMap.get(
|
||||
"intensity").get(k)).getIntData();
|
||||
float[] latitudeData = ((FloatDataRecord) recordMap.get(
|
||||
"latitude").get(k)).getFloatData();
|
||||
float[] longitudeData = ((FloatDataRecord) recordMap.get(
|
||||
"longitude").get(k)).getFloatData();
|
||||
|
||||
int[] intensityData = ((IntegerDataRecord) intensities
|
||||
.get(k)).getIntData();
|
||||
float[] latitudeData = ((FloatDataRecord) lats.get(k))
|
||||
.getFloatData();
|
||||
float[] longitudeData = ((FloatDataRecord) lons.get(k))
|
||||
.getFloatData();
|
||||
|
||||
for (int i = 0; i < numRecords; i++) {
|
||||
|
||||
|
|
27
deltaScripts/14.4.1/DR3213/renameLightningStrikeCount.py
Executable file
27
deltaScripts/14.4.1/DR3213/renameLightningStrikeCount.py
Executable file
|
@ -0,0 +1,27 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import h5py
|
||||
import os
|
||||
import sys
|
||||
|
||||
# multiplicity was incorrectly interpreted as 'stike count' when
|
||||
# it was the number of strokes (AKA pulses) in the strike (AKA flash)
|
||||
|
||||
LIGHTNING_H5_PATH = '/awips2/edex/data/hdf5/binlightning'
|
||||
OLD_NAME = 'strikeCount'
|
||||
NEW_NAME = 'pulseCount'
|
||||
|
||||
for file in os.listdir(LIGHTNING_H5_PATH):
|
||||
if file.endswith('h5'):
|
||||
h5file = None
|
||||
try:
|
||||
fileName = os.path.join(LIGHTNING_H5_PATH, file)
|
||||
h5file = h5py.File(fileName, 'r+')
|
||||
for g in h5file.values():
|
||||
if NEW_NAME not in g and OLD_NAME in g:
|
||||
g[NEW_NAME] = g[OLD_NAME]
|
||||
except Exception, e:
|
||||
print "Error renaming strikeCount in file", fileName, ":", e
|
||||
finally:
|
||||
if h5file:
|
||||
h5file.close()
|
|
@ -9,6 +9,7 @@ Export-Package: com.raytheon.edex.plugin.binlightning.dao
|
|||
Import-Package: com.raytheon.edex.esb,
|
||||
com.raytheon.edex.exception,
|
||||
com.raytheon.edex.plugin,
|
||||
com.raytheon.uf.common.numeric,
|
||||
com.raytheon.uf.common.status,
|
||||
com.raytheon.uf.common.wmo,
|
||||
gov.noaa.nws.ost.edex.plugin.binlightning,
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
<bean id="binlightningDecoder"
|
||||
class="com.raytheon.edex.plugin.binlightning.BinLightningDecoder" />
|
||||
|
||||
<bean id="totalLightningDecoder" class="com.raytheon.edex.plugin.binlightning.total.TotalLightningDecoder" />
|
||||
|
||||
<bean id="binlightningDistRegistry" factory-bean="distributionSrv"
|
||||
factory-method="register">
|
||||
|
@ -16,42 +18,37 @@
|
|||
<constructor-arg ref="clusteredBinLightningRoutes" />
|
||||
</bean>
|
||||
|
||||
<camelContext id="clusteredBinLightningRoutes"
|
||||
xmlns="http://camel.apache.org/schema/spring"
|
||||
errorHandlerRef="errorHandler">
|
||||
<!--
|
||||
<endpoint id="binlightningFileEndpoint"
|
||||
uri="file:${edex.home}/data/sbn/binlightning?noop=true&idempotent=false" />
|
||||
|
||||
<route id="binlightningFileConsumerRoute">
|
||||
<from ref="binlightningFileEndpoint" />
|
||||
<bean ref="fileToString" />
|
||||
<setHeader headerName="pluginName">
|
||||
<constant>binlightning</constant>
|
||||
</setHeader>
|
||||
<to uri="jms-durable:queue:Ingest.binlightning" />
|
||||
</route>
|
||||
-->
|
||||
<camelContext id="clusteredBinLightningRoutes" xmlns="http://camel.apache.org/schema/spring"
|
||||
errorHandlerRef="errorHandler">
|
||||
|
||||
<!-- Begin binlightning routes -->
|
||||
<route id="binlightningIngestRoute">
|
||||
<from uri="jms-durable:queue:Ingest.binlightning"/>
|
||||
<setHeader headerName="pluginName">
|
||||
<constant>binlightning</constant>
|
||||
</setHeader>
|
||||
<doTry>
|
||||
<pipeline>
|
||||
<bean ref="stringToFile" />
|
||||
<bean ref="binlightningDecoder" method="decode" />
|
||||
<to uri="direct-vm:persistIndexAlert" />
|
||||
<route id="binlightningIngestRoute">
|
||||
<from uri="jms-durable:queue:Ingest.binlightning" />
|
||||
<setHeader headerName="pluginName">
|
||||
<constant>binlightning</constant>
|
||||
</setHeader>
|
||||
<doTry>
|
||||
<pipeline>
|
||||
<bean ref="stringToFile" />
|
||||
<choice>
|
||||
<when>
|
||||
<simple>${in.header.header} regex '^SFPA42 KWBC.*'</simple>
|
||||
<bean ref="totalLightningDecoder" method="decode" />
|
||||
</when>
|
||||
<otherwise>
|
||||
<bean ref="binlightningDecoder" method="decode" />
|
||||
</otherwise>
|
||||
</choice>
|
||||
|
||||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:binlightning?level=ERROR"/>
|
||||
</doCatch>
|
||||
</doTry>
|
||||
<to uri="direct-vm:persistIndexAlert" />
|
||||
|
||||
</pipeline>
|
||||
<doCatch>
|
||||
<exception>java.lang.Throwable</exception>
|
||||
<to uri="log:binlightning?level=ERROR" />
|
||||
</doCatch>
|
||||
</doTry>
|
||||
<!-- bean ref="processUtil" method="delete" / -->
|
||||
</route>
|
||||
</camelContext>
|
||||
</route>
|
||||
</camelContext>
|
||||
</beans>
|
|
@ -47,8 +47,6 @@ import com.raytheon.uf.common.dataplugin.binlightning.impl.LightningStrikePoint;
|
|||
import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgStrikeType;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.time.DataTime;
|
||||
import com.raytheon.uf.common.time.TimeRange;
|
||||
import com.raytheon.uf.common.time.util.TimeUtil;
|
||||
import com.raytheon.uf.common.wmo.WMOHeader;
|
||||
import com.raytheon.uf.common.wmo.WMOTimeParser;
|
||||
|
@ -58,17 +56,6 @@ import com.raytheon.uf.edex.decodertools.core.IBinDataSource;
|
|||
/**
|
||||
* AWIPS decoder adapter strategy for binary lightning data.<br/>
|
||||
*
|
||||
* Normal usage for this adapter is<br/>
|
||||
* <code>
|
||||
* BinLightningDecoder dec = new BinLightningDecoder();
|
||||
* dec.setMessage(data);
|
||||
* while(dec.hasNext())
|
||||
* {
|
||||
* BinLightningRecord r = dec.decode();
|
||||
* // do something with record.
|
||||
* }
|
||||
* dec.dispose();
|
||||
* </code>
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
|
@ -98,6 +85,7 @@ import com.raytheon.uf.edex.decodertools.core.IBinDataSource;
|
|||
* Jun 03, 2014 3226 bclement removed unused WMO patterns, switched to UFStatus
|
||||
* removed TimeTools usage, removed constructDataURI() call
|
||||
* added decodeBinLightningData() and decodeBitShiftedBinLightningData() from BinLightningDecoderUtil
|
||||
* Jun 05, 2014 3226 bclement LightningStikePoint refactor, added extractPData()
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -118,7 +106,7 @@ public class BinLightningDecoder extends AbstractDecoder {
|
|||
* Default lightning strike type for FLASH messages. RT_FLASH documents
|
||||
* indicate no default, but D2D code defaults to STRIKE_CG also.
|
||||
*/
|
||||
public LtgStrikeType DEFAULT_FLASH_TYPE = LtgStrikeType.STRIKE_CG;
|
||||
public LtgStrikeType DEFAULT_FLASH_TYPE = LtgStrikeType.CLOUD_TO_GROUND;
|
||||
|
||||
private String traceId = null;
|
||||
|
||||
|
@ -153,30 +141,37 @@ public class BinLightningDecoder extends AbstractDecoder {
|
|||
Calendar baseTime = WMOTimeParser.findDataTime(
|
||||
wmoHdr.getYYGGgg(), fileName);
|
||||
|
||||
// Because binary nature of the encrypted data, the string created with its byte[] array may not have the same length of the byte[] array length
|
||||
// So when DecoderTools.stripWMOHeader() assumes byte[] length == String length in its logic, it is observed that it may return a shorter byte[] than
|
||||
// the real data array. (Looks like a bug???)
|
||||
/*
|
||||
* Because binary nature of the encrypted data, the string
|
||||
* created with its byte[] array may not have the same length of
|
||||
* the byte[] array length So when DecoderTools.stripWMOHeader()
|
||||
* assumes byte[] length == String length in its logic, it is
|
||||
* observed that it may return a shorter byte[] than the real
|
||||
* data array. (Looks like a bug???)
|
||||
*/
|
||||
// byte[] pdata = DecoderTools.stripWMOHeader(data, SFUS_PATTERN);
|
||||
// if (pdata == null) {
|
||||
// pdata = DecoderTools.stripWMOHeader(data, SFPA_PATTERN);
|
||||
// }
|
||||
// instead the following is used to strip WMO header a little more safely.
|
||||
byte[] pdata = null;
|
||||
if (wmoHdr.isValid() && wmoHdr.getMessageDataStart() > 0) {
|
||||
pdata = new byte[data.length - wmoHdr.getMessageDataStart()];
|
||||
System.arraycopy(data, wmoHdr.getMessageDataStart(), pdata, 0, data.length - wmoHdr.getMessageDataStart());
|
||||
}
|
||||
/*
|
||||
* instead the following is used to strip WMO header a little
|
||||
* more safely.
|
||||
*/
|
||||
byte[] pdata = extractPData(wmoHdr, data);
|
||||
|
||||
if ((pdata == null) || (pdata.length == 0)) {
|
||||
return new PluginDataObject[0];
|
||||
}
|
||||
|
||||
//
|
||||
// Modified by Wufeng Zhou to handle both legacy bit-shifted and new encryted data
|
||||
//
|
||||
// Preserved the legacy decoding in BinLigntningDecoderUtil.decodeBitShiftedBinLightningData(), and added logic to process
|
||||
// both encrypted data and legacy data
|
||||
//
|
||||
/*
|
||||
* Modified by Wufeng Zhou to handle both legacy bit-shifted and
|
||||
* new encryted data
|
||||
*
|
||||
* Preserved the legacy decoding in
|
||||
* BinLigntningDecoderUtil.decodeBitShiftedBinLightningData(),
|
||||
* and added logic to process both encrypted data and legacy
|
||||
* data
|
||||
*/
|
||||
|
||||
List<LightningStrikePoint> strikes = decodeBinLightningData(
|
||||
data, pdata, traceId, wmoHdr, baseTime.getTime());
|
||||
|
@ -186,18 +181,14 @@ public class BinLightningDecoder extends AbstractDecoder {
|
|||
return reports;
|
||||
}
|
||||
|
||||
//
|
||||
// Done MOD by Wufeng Zhou
|
||||
//
|
||||
/*
|
||||
* Done MOD by Wufeng Zhou
|
||||
*/
|
||||
|
||||
// post processing data - if not keep-alive record
|
||||
BinLightningRecord report = null;
|
||||
if (strikes.size() > 0) {
|
||||
report = new BinLightningRecord(strikes.size());
|
||||
for (LightningStrikePoint strike : strikes) {
|
||||
report.addStrike(strike);
|
||||
logger.debug(traceId + "-" + strike);
|
||||
}
|
||||
report = new BinLightningRecord(strikes);
|
||||
} else {
|
||||
return new PluginDataObject[0];
|
||||
}
|
||||
|
@ -215,18 +206,8 @@ public class BinLightningDecoder extends AbstractDecoder {
|
|||
+ " at " + SDF.format(cStart.getTime()));
|
||||
}
|
||||
} else {
|
||||
Calendar cStop = report.getStopTime();
|
||||
|
||||
TimeRange range = new TimeRange(cStart.getTimeInMillis(),
|
||||
cStop.getTimeInMillis());
|
||||
|
||||
DataTime dataTime = new DataTime(cStart, range);
|
||||
report.setDataTime(dataTime);
|
||||
|
||||
if (report != null) {
|
||||
report.setTraceId(traceId);
|
||||
reports = new PluginDataObject[] { report };
|
||||
}
|
||||
report.setTraceId(traceId);
|
||||
reports = new PluginDataObject[] { report };
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -235,6 +216,23 @@ public class BinLightningDecoder extends AbstractDecoder {
|
|||
return reports;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove WMO header from data and return the remaining pdata
|
||||
*
|
||||
* @param wmoHdr
|
||||
* @param data
|
||||
* @return null if data is invalid
|
||||
*/
|
||||
public static byte[] extractPData(WMOHeader wmoHdr, byte[] data) {
|
||||
byte[] pdata = null;
|
||||
if (wmoHdr.isValid() && wmoHdr.getMessageDataStart() > 0) {
|
||||
pdata = new byte[data.length - wmoHdr.getMessageDataStart()];
|
||||
System.arraycopy(data, wmoHdr.getMessageDataStart(), pdata, 0,
|
||||
data.length - wmoHdr.getMessageDataStart());
|
||||
}
|
||||
return pdata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode bin lightning data, able to handle both legacy bit-shifted and new
|
||||
* encryted data
|
||||
|
@ -281,50 +279,52 @@ public class BinLightningDecoder extends AbstractDecoder {
|
|||
boolean decodeDone = false;
|
||||
EncryptedBinLightningCipher cipher = new EncryptedBinLightningCipher();
|
||||
|
||||
//
|
||||
// Using different WMO headers to indicate whether the data is encrypted
|
||||
// or not would be a nice option.
|
||||
// However, that idea has been discussed but not adopted.
|
||||
// If in the future, WMO header can be different for legacy and
|
||||
// encrypted data, or some other metadata can be used to decide
|
||||
// whether deceyption is needed, logic can be added here.
|
||||
//
|
||||
// Before that happens, we'll use hints and trial & error to decode the
|
||||
// data
|
||||
// Hints: Per lightning data format spec, there are 3 bytes in the WMO
|
||||
// header starting line that indicates the size of the encrypted block
|
||||
// or the ASCII sequence # for legacy bit-shifted data
|
||||
// However, the starting line is optional and AWIPS decode may not see
|
||||
// it at all because TG will strip that starting line away
|
||||
// We'll try to use this hint first, if is is not found, then trial and
|
||||
// error way to decrypt and decode
|
||||
//
|
||||
// As of 11/05/2013, There is change in data spec. that the 3-bytes will
|
||||
// not be encoded as encrypted block size anymore (it will always be
|
||||
// transmission sequence # if present)
|
||||
// So there should have some minor changes in the logic below for
|
||||
// decoding the data.
|
||||
// However, as reading into the
|
||||
// com.raytheon.edex.plugin.binlightning.impl.BinLightningFactory.getDecoder()
|
||||
// and follow-on code, we see the following data patterns
|
||||
// for legacy bit-shifted data, which could be used to reduce guess-work
|
||||
// in data decryption:
|
||||
// The bit-shifted data will have multiple groups of the following
|
||||
// patterns:
|
||||
// 1-byte (unsigned byte): for size count
|
||||
// 1-byte (unsigned byte): for flash type:
|
||||
// 0x96 for FLASH_RPT (message size is 6 bytes each)
|
||||
// 0x97 for RT_FLASH_RPT (message size is 8 bytes each)
|
||||
// 0xd0 for OTHER_RPT (The D2D decoders declare but do not define this
|
||||
// message, so unimplemented decoder)
|
||||
// 0xd1 for COMM_RPT (The D2D decoders declare but do not define this
|
||||
// message, so unimplemented decoder)
|
||||
// 4-bytes: date time
|
||||
// multiple of 6 or 8 bytes (as determined by 2nd byte flash type) with
|
||||
// count indicated in 1st byte
|
||||
//
|
||||
// So this is be used to determine whether the data need to be
|
||||
// decrypted.
|
||||
/*
|
||||
* Using different WMO headers to indicate whether the data is encrypted
|
||||
* or not would be a nice option.
|
||||
* However, that idea has been discussed but not adopted.
|
||||
* If in the future, WMO header can be different for legacy and
|
||||
* encrypted data, or some other metadata can be used to decide
|
||||
* whether deceyption is needed, logic can be added here.
|
||||
*
|
||||
* Before that happens, we'll use hints and trial & error to decode the
|
||||
* data
|
||||
* Hints: Per lightning data format spec, there are 3 bytes in the WMO
|
||||
* header starting line that indicates the size of the encrypted block
|
||||
* or the ASCII sequence # for legacy bit-shifted data
|
||||
* However, the starting line is optional and AWIPS decode may not see
|
||||
* it at all because TG will strip that starting line away
|
||||
* We'll try to use this hint first, if is is not found, then trial and
|
||||
* error way to decrypt and decode
|
||||
*
|
||||
* As of 11/05/2013, There is change in data spec. that the 3-bytes will
|
||||
* not be encoded as encrypted block size anymore (it will always be
|
||||
* transmission sequence # if present)
|
||||
* So there should have some minor changes in the logic below for
|
||||
* decoding the data.
|
||||
* However, as reading into the
|
||||
* com.raytheon.edex.plugin.binlightning.impl.BinLightningFactory.getDecoder
|
||||
* ()
|
||||
* and follow-on code, we see the following data patterns
|
||||
* for legacy bit-shifted data, which could be used to reduce guess-work
|
||||
* in data decryption:
|
||||
* The bit-shifted data will have multiple groups of the following
|
||||
* patterns:
|
||||
* 1-byte (unsigned byte): for size count
|
||||
* 1-byte (unsigned byte): for flash type:
|
||||
* 0x96 for FLASH_RPT (message size is 6 bytes each)
|
||||
* 0x97 for RT_FLASH_RPT (message size is 8 bytes each)
|
||||
* 0xd0 for OTHER_RPT (The D2D decoders declare but do not define this
|
||||
* message, so unimplemented decoder)
|
||||
* 0xd1 for COMM_RPT (The D2D decoders declare but do not define this
|
||||
* message, so unimplemented decoder)
|
||||
* 4-bytes: date time
|
||||
* multiple of 6 or 8 bytes (as determined by 2nd byte flash type) with
|
||||
* count indicated in 1st byte
|
||||
*
|
||||
* So this is be used to determine whether the data need to be
|
||||
* decrypted.
|
||||
*/
|
||||
|
||||
/*
|
||||
* // looks like previous assumption on block size bytes are not valid
|
||||
|
@ -343,21 +343,23 @@ public class BinLightningDecoder extends AbstractDecoder {
|
|||
|
||||
if (needDecrypt) {
|
||||
try {
|
||||
// NOTE: 11/14/2013 WZ:
|
||||
// encrypted test data on TNCF (got from Melissa Porricelli)
|
||||
// seems to have extra 4 bytes (0x0d 0x0d 0x0a 0x03) at the end,
|
||||
// making the data size not a multiple of 16. However, original
|
||||
// test data do not have this trailing bytes. while NCEP test
|
||||
// data has extra 8 trailing bytes.
|
||||
// Brain Rapp's email on 11/13/2013 confirms that Unidata LDM
|
||||
// software used by AWIPS II will strips off all SBN protocol
|
||||
// headers
|
||||
// that precede the WMO header and adds its own 11 byte header
|
||||
// like this: "soh cr cr nl 2 5 4 sp cr cr nl". It
|
||||
// also adds a four byte trailer consisting of "cr cr nl etx"
|
||||
// (0x0d 0x0d 0x0a 0x03)
|
||||
// So, it seems necessary to trim trailing bytes if it is not
|
||||
// multiple of 16, warning messages will be logged though
|
||||
/*
|
||||
* NOTE: 11/14/2013 WZ:
|
||||
* encrypted test data on TNCF (got from Melissa Porricelli)
|
||||
* seems to have extra 4 bytes (0x0d 0x0d 0x0a 0x03) at the end,
|
||||
* making the data size not a multiple of 16. However, original
|
||||
* test data do not have this trailing bytes. while NCEP test
|
||||
* data has extra 8 trailing bytes.
|
||||
* Brain Rapp's email on 11/13/2013 confirms that Unidata LDM
|
||||
* software used by AWIPS II will strips off all SBN protocol
|
||||
* headers
|
||||
* that precede the WMO header and adds its own 11 byte header
|
||||
* like this: "soh cr cr nl 2 5 4 sp cr cr nl". It
|
||||
* also adds a four byte trailer consisting of "cr cr nl etx"
|
||||
* (0x0d 0x0d 0x0a 0x03)
|
||||
* So, it seems necessary to trim trailing bytes if it is not
|
||||
* multiple of 16, warning messages will be logged though
|
||||
*/
|
||||
int dataLengthToBeDecrypted = pdata.length;
|
||||
if (pdata.length % 16 != 0) {
|
||||
dataLengthToBeDecrypted = pdata.length
|
||||
|
@ -382,8 +384,10 @@ public class BinLightningDecoder extends AbstractDecoder {
|
|||
decodeDone = true;
|
||||
return null;
|
||||
}
|
||||
// not keep-alive record, then check data validity and decode
|
||||
// into an ArrayList<LightningStrikePoint> of strikes
|
||||
/*
|
||||
* not keep-alive record, then check data validity and decode
|
||||
* into an ArrayList<LightningStrikePoint> of strikes
|
||||
*/
|
||||
if (BinLightningDecoderUtil
|
||||
.isLightningDataRecords(decryptedData)) {
|
||||
strikes = BinLightningDecoderUtil
|
||||
|
@ -418,9 +422,11 @@ public class BinLightningDecoder extends AbstractDecoder {
|
|||
if (decodeDone == false) { // not decoded through decrypt->decode
|
||||
// process, try the legacy decoder
|
||||
logger.info(traceId + " - decoding as bit-shifted data");
|
||||
// bit-shifting data format check call here will get us some more
|
||||
// information on the data, also can compare the strikes with the
|
||||
// decoder result
|
||||
/*
|
||||
* bit-shifting data format check call here will get us some more
|
||||
* information on the data, also can compare the strikes with the
|
||||
* decoder result
|
||||
*/
|
||||
int estimatedStrikes = BinLightningDecoderUtil
|
||||
.getBitShiftedDataStrikeCount(pdata);
|
||||
strikes = decodeBitShiftedBinLightningData(pdata, wmoHdr);
|
||||
|
@ -461,13 +467,15 @@ public class BinLightningDecoder extends AbstractDecoder {
|
|||
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.)
|
||||
/*
|
||||
* 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",
|
||||
|
|
|
@ -20,11 +20,17 @@
|
|||
|
||||
package com.raytheon.edex.plugin.binlightning.dao;
|
||||
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.BinLightningRecord;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.raytheon.uf.common.dataplugin.PluginException;
|
||||
import com.raytheon.uf.common.dataplugin.annotations.DataURI;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.BinLightningRecord;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.LightningConstants;
|
||||
import com.raytheon.uf.common.dataplugin.persist.IPersistable;
|
||||
import com.raytheon.uf.common.datastorage.DataStoreFactory;
|
||||
import com.raytheon.uf.common.datastorage.IDataStore;
|
||||
import com.raytheon.uf.common.datastorage.StorageException;
|
||||
import com.raytheon.uf.common.datastorage.records.IDataRecord;
|
||||
import com.raytheon.uf.edex.database.plugin.PluginDao;
|
||||
|
||||
|
@ -36,6 +42,7 @@ import com.raytheon.uf.edex.database.plugin.PluginDao;
|
|||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* 1/08/09 1674 bphillip Initial creation
|
||||
* Jun 05, 2014 3226 bclement record now contains maps for data arrays
|
||||
* </pre>
|
||||
*
|
||||
* @author bphillip
|
||||
|
@ -61,15 +68,38 @@ public class BinLightningDao extends PluginDao {
|
|||
protected IDataStore populateDataStore(IDataStore dataStore,
|
||||
IPersistable obj) throws Exception {
|
||||
BinLightningRecord binLightningRec = (BinLightningRecord) obj;
|
||||
|
||||
for (int i = 0; i < binLightningRec.getDataArrays().length; i++) {
|
||||
IDataRecord record = DataStoreFactory.createStorageRecord(
|
||||
binLightningRec.getDataNames()[i], binLightningRec
|
||||
.getDataURI(), binLightningRec.getDataArrays()[i]);
|
||||
record.setCorrelationObject(binLightningRec);
|
||||
dataStore.addDataRecord(record);
|
||||
}
|
||||
|
||||
Map<String, Object> strikeDataArrays = binLightningRec
|
||||
.getStrikeDataArrays();
|
||||
populateFromMap(dataStore, obj, binLightningRec.getDataURI(),
|
||||
strikeDataArrays);
|
||||
Map<String, Object> pulseDataArrays = binLightningRec
|
||||
.getPulseDataArrays();
|
||||
String pulseGroup = binLightningRec.getDataURI() + DataURI.SEPARATOR
|
||||
+ LightningConstants.PULSE_HDF5_GROUP_SUFFIX;
|
||||
populateFromMap(dataStore, obj, pulseGroup, pulseDataArrays);
|
||||
return dataStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds each primitive data array object in map to the datastore using the
|
||||
* provided group and the key of the map entry as the name
|
||||
*
|
||||
* @param dataStore
|
||||
* @param obj
|
||||
* @param group
|
||||
* @param data
|
||||
* @throws StorageException
|
||||
*/
|
||||
private void populateFromMap(IDataStore dataStore, IPersistable obj,
|
||||
String group, Map<String, Object> data)
|
||||
throws StorageException {
|
||||
for (Entry<String, Object> e : data.entrySet()) {
|
||||
String name = e.getKey();
|
||||
Object dataArray = e.getValue();
|
||||
IDataRecord record = DataStoreFactory.createStorageRecord(name,
|
||||
group, dataArray);
|
||||
record.setCorrelationObject(obj);
|
||||
dataStore.addDataRecord(record);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ import java.util.List;
|
|||
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.impl.LightningStrikePoint;
|
||||
import com.raytheon.uf.common.time.util.TimeUtil;
|
||||
import com.raytheon.uf.edex.decodertools.core.BasePoint;
|
||||
import com.raytheon.uf.edex.decodertools.core.IBinDataSource;
|
||||
|
||||
/**
|
||||
|
@ -42,6 +41,7 @@ import com.raytheon.uf.edex.decodertools.core.IBinDataSource;
|
|||
* 20070810 379 jkorman Initial Coding from prototype.
|
||||
* 20070912 379 jkorman Code review cleanup.
|
||||
* May 14, 2014 2536 bclement removed TimeTools
|
||||
* Jun 05, 2014 3226 bclement parseDate() now returns calendar
|
||||
* </pre>
|
||||
*
|
||||
* @author jkorman
|
||||
|
@ -87,13 +87,12 @@ abstract class BaseLightningDecoder implements IBinLightningDecoder
|
|||
/**
|
||||
* Parse the date field from a given data source. It is assumed that the
|
||||
* data source is pointing to the current date/time data.
|
||||
* @return A BasePoint object with the time fields set to the observation
|
||||
* time.
|
||||
*
|
||||
* @return A Calendar object with the time fields set to the observation
|
||||
* time.
|
||||
*/
|
||||
BasePoint parseDate(IBinDataSource msgData)
|
||||
protected Calendar parseDate(IBinDataSource msgData)
|
||||
{
|
||||
BasePoint point = new BasePoint();
|
||||
|
||||
//********* Don't reorder these reads!!!
|
||||
int b1 = msgData.getU8();
|
||||
int b2 = msgData.getU8();
|
||||
|
@ -103,22 +102,18 @@ abstract class BaseLightningDecoder implements IBinLightningDecoder
|
|||
// number of days since BASE_TIME
|
||||
int days = ((word1 & DAYS_MASK) >> DAYS_SHFT);
|
||||
obsTime.add(Calendar.DAY_OF_MONTH, days);
|
||||
|
||||
point.setYear(obsTime.get(Calendar.YEAR));
|
||||
//Increment month, Calendar returns 0..11
|
||||
point.setMonth(obsTime.get(Calendar.MONTH) + 1);
|
||||
point.setDay(obsTime.get(Calendar.DAY_OF_MONTH));
|
||||
|
||||
int hours = (word1 & HOURS_HI_BIT_MASK) << HOURS_HI_BIT_SHFT;
|
||||
hours += (b2 & HOURS_LO_NYB_MASK) >>> HOURS_LO_NYB_SHFT;
|
||||
point.setHour(hours);
|
||||
obsTime.set(Calendar.HOUR, hours);
|
||||
|
||||
int minutes = (b2 & MIN_P1_MASK) << MIN_P1_SHFT;
|
||||
minutes += (b1 & MIN_P2_MASK) >>> MIN_P2_SHFT;
|
||||
point.setMinute(minutes);
|
||||
obsTime.set(Calendar.MINUTE, minutes);
|
||||
|
||||
point.setSecond((b1 & SECONDS_MASK));
|
||||
return point;
|
||||
obsTime.set(Calendar.SECOND, (b1 & SECONDS_MASK));
|
||||
obsTime.set(Calendar.MILLISECOND, 0);
|
||||
return obsTime;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,9 +19,11 @@
|
|||
**/
|
||||
package com.raytheon.edex.plugin.binlightning.impl;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.impl.LightningStrikePoint;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgMsgType;
|
||||
import com.raytheon.uf.edex.decodertools.core.BasePoint;
|
||||
import com.raytheon.uf.common.time.util.TimeUtil;
|
||||
import com.raytheon.uf.edex.decodertools.core.IBinDataSource;
|
||||
|
||||
/**
|
||||
|
@ -30,13 +32,14 @@ import com.raytheon.uf.edex.decodertools.core.IBinDataSource;
|
|||
*
|
||||
* <pre>
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* 20070810 379 jkorman Initial Coding from prototype.
|
||||
* Jun 05, 2014 3226 bclement LightningStikePoint refactor
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @author jkorman
|
||||
* @version 1.0
|
||||
*/
|
||||
|
@ -62,7 +65,7 @@ public class FlashLightningDecoder extends BaseLightningDecoder
|
|||
{
|
||||
if(msgData.available(TIME_SIZE))
|
||||
{
|
||||
BasePoint base = parseDate(msgData);
|
||||
Calendar baseTime = parseDate(msgData);
|
||||
|
||||
if(msgData.available(FLASH_MSG_SIZE * count))
|
||||
{
|
||||
|
@ -70,17 +73,23 @@ public class FlashLightningDecoder extends BaseLightningDecoder
|
|||
{
|
||||
double lon = getFlashLon(msgData);
|
||||
double lat = getFlashLat(msgData);
|
||||
// Create the strike record from the report info and base time information.
|
||||
LightningStrikePoint strikeData = new LightningStrikePoint(base,lat,lon,LtgMsgType.STRIKE_MSG_FL);
|
||||
|
||||
strikeData.setStrikeStrength(msgData.getS8() * 2.0);
|
||||
|
||||
double strikeStrength = msgData.getS8() * 2.0;
|
||||
|
||||
// strike count and 1/10s seconds
|
||||
int u8 = msgData.getU8();
|
||||
strikeData.setStrikeCount(u8 & 0x0F);
|
||||
strikeData.setMillis(((u8 & 0xF0) >> 4) * 100);
|
||||
int flashCount = u8 & 0x0F;
|
||||
|
||||
Calendar obsTime = TimeUtil.newCalendar(baseTime);
|
||||
obsTime.set(Calendar.MILLISECOND, ((u8 & 0xF0) >> 4) * 100);
|
||||
|
||||
// Create the strike record from the report info and base
|
||||
// time information.
|
||||
LightningStrikePoint strikeData = new LightningStrikePoint(
|
||||
lat, lon, baseTime, LtgMsgType.STRIKE_MSG_FL);
|
||||
strikeData.setType(DEFAULT_FLASH_TYPE);
|
||||
strikeData.setStrikeStrength(strikeStrength);
|
||||
strikeData.setPulseCount(flashCount);
|
||||
addStrike(strikeData);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,22 +26,24 @@ import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgStrikeType;
|
|||
* Declare the interface for binary lightning decoding. The decoders are
|
||||
* expected to implement an Iterable interface. Data decoding will take place
|
||||
* during construction of the element.
|
||||
*
|
||||
* <pre>
|
||||
* the recommended constructor for this interface is
|
||||
*
|
||||
* @param data An IBinDataSource data source containing the data to be decoded.
|
||||
* @param count The number of records that this decoder should see.
|
||||
* <code>public X (IBinDataSource data, int count)</code>
|
||||
*
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* 20070810 379 jkorman Initial Coding from prototype.
|
||||
* 20070912 379 jkorman Code review cleanup.
|
||||
* Jun 05, 2014 3226 bclement LightningStikePoint refactor
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @author jkorman
|
||||
* @version 1.0
|
||||
*/
|
||||
|
@ -59,7 +61,7 @@ public interface IBinLightningDecoder extends Iterable<LightningStrikePoint>
|
|||
public static final int OTHER_RPT = 0xD0;
|
||||
public static final int COMM_RPT = 0xD1;
|
||||
|
||||
public static final LtgStrikeType DEFAULT_FLASH_TYPE = LtgStrikeType.STRIKE_CG;
|
||||
public static final LtgStrikeType DEFAULT_FLASH_TYPE = LtgStrikeType.CLOUD_TO_GROUND;
|
||||
|
||||
/*
|
||||
*/
|
||||
|
|
|
@ -19,9 +19,10 @@
|
|||
**/
|
||||
package com.raytheon.edex.plugin.binlightning.impl;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.impl.LightningStrikePoint;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgMsgType;
|
||||
import com.raytheon.uf.edex.decodertools.core.BasePoint;
|
||||
import com.raytheon.uf.edex.decodertools.core.IBinDataSource;
|
||||
|
||||
/**
|
||||
|
@ -37,6 +38,7 @@ import com.raytheon.uf.edex.decodertools.core.IBinDataSource;
|
|||
* 20070810 379 jkorman Initial Coding from prototype.
|
||||
* 20070821 379 jkorman Added default strike type.
|
||||
* 20080823 379 jkorman getRTLat was using 24 bits instead of 23.
|
||||
* Jun 05, 2014 3226 bclement LightningStikePoint refactor
|
||||
* </pre>
|
||||
*
|
||||
* @author jkorman
|
||||
|
@ -66,7 +68,7 @@ public class RTLightningDecoder extends BaseLightningDecoder {
|
|||
*/
|
||||
private void doDecode(IBinDataSource msgData, int count) {
|
||||
if (msgData.available(TIME_SIZE + (RT_MSG_SIZE * count))) {
|
||||
BasePoint base = parseDate(msgData);
|
||||
Calendar baseTime = parseDate(msgData);
|
||||
// for now just consume some data
|
||||
for (int i = 0; i < count; i++) {
|
||||
long part = msgData.getU32();
|
||||
|
@ -79,11 +81,11 @@ public class RTLightningDecoder extends BaseLightningDecoder {
|
|||
double lat = getRTLat(part);
|
||||
int strikeCount = getMult(part);
|
||||
|
||||
LightningStrikePoint strikeData = new LightningStrikePoint(
|
||||
base, lat, lon, LtgMsgType.STRIKE_MSG_RT);
|
||||
LightningStrikePoint strikeData = new LightningStrikePoint(lat,
|
||||
lon, baseTime, LtgMsgType.STRIKE_MSG_RT);
|
||||
|
||||
strikeData.setStrikeStrength(strength);
|
||||
strikeData.setStrikeCount(strikeCount);
|
||||
strikeData.setPulseCount(strikeCount);
|
||||
// *****
|
||||
// NCDC documents indicate that RT data can report both CC/CG
|
||||
// but haven't seen any data nor is it in the D2D decoders. Set
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
/**
|
||||
* 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 com.raytheon.edex.plugin.binlightning.total;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.raytheon.uf.common.numeric.UnsignedNumbers;
|
||||
|
||||
/**
|
||||
* ByteBuffer wrapper that keeps track of checksums
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 3, 2014 3226 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public class ChecksumByteBuffer {
|
||||
|
||||
private static final int SHORT_SIZE = Short.SIZE / Byte.SIZE;
|
||||
|
||||
private static final int INT_SIZE = Integer.SIZE / Byte.SIZE;
|
||||
|
||||
private static final int LONG_SIZE = Integer.SIZE / Byte.SIZE;
|
||||
|
||||
private final ByteBuffer buff;
|
||||
|
||||
private long totalSum;
|
||||
|
||||
private long packetSum;
|
||||
|
||||
|
||||
/**
|
||||
* @see ByteBuffer#wrap(byte[])
|
||||
* @param data
|
||||
*/
|
||||
public ChecksumByteBuffer(byte[] data) {
|
||||
this.buff = ByteBuffer.wrap(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the sum of the next numberOfBytes worth of data
|
||||
*
|
||||
* @param numberOfBytes
|
||||
* @return
|
||||
*/
|
||||
private long getSum(int numberOfBytes) {
|
||||
int start = buff.position();
|
||||
int end = start + numberOfBytes;
|
||||
long rval = 0;
|
||||
for (int i = start; i < end; ++i) {
|
||||
rval += UnsignedNumbers.ubyteToShort(buff.get(i));
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ByteBuffer#get()
|
||||
* @return
|
||||
*/
|
||||
public byte get() {
|
||||
byte rval = buff.get();
|
||||
short unsignedRval = UnsignedNumbers.ubyteToShort(rval);
|
||||
totalSum += unsignedRval;
|
||||
packetSum += unsignedRval;
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ByteBuffer#getShort()
|
||||
* @return
|
||||
*/
|
||||
public short getShort() {
|
||||
long sum = getSum(SHORT_SIZE);
|
||||
totalSum += sum;
|
||||
packetSum += sum;
|
||||
return buff.getShort();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ByteBuffer#getInt()
|
||||
* @return
|
||||
*/
|
||||
public int getInt() {
|
||||
long sum = getSum(INT_SIZE);
|
||||
totalSum += sum;
|
||||
packetSum += sum;
|
||||
return buff.getInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ByteBuffer#getLong()
|
||||
* @return
|
||||
*/
|
||||
public long getLong() {
|
||||
long sum = getSum(LONG_SIZE);
|
||||
totalSum += sum;
|
||||
packetSum += sum;
|
||||
return buff.getLong();
|
||||
}
|
||||
|
||||
/**
|
||||
* reset the current packet sum to zero
|
||||
*/
|
||||
public void resetPacketSum() {
|
||||
packetSum = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* reset all sums to zero
|
||||
*/
|
||||
public void resetAllSums() {
|
||||
resetPacketSum();
|
||||
totalSum = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the totalSum
|
||||
*/
|
||||
public long getTotalSum() {
|
||||
return totalSum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the packetSum
|
||||
*/
|
||||
public long getPacketSum() {
|
||||
return packetSum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ByteBuffer#limit()
|
||||
* @return
|
||||
*/
|
||||
public int size() {
|
||||
return buff.limit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ByteBuffer#position()
|
||||
* @return
|
||||
*/
|
||||
public int position() {
|
||||
return buff.position();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,348 @@
|
|||
/**
|
||||
* 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 com.raytheon.edex.plugin.binlightning.total;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import com.raytheon.edex.esb.Headers;
|
||||
import com.raytheon.edex.exception.DecoderException;
|
||||
import com.raytheon.edex.plugin.binlightning.BinLightningDecoder;
|
||||
import com.raytheon.uf.common.dataplugin.PluginDataObject;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.BinLightningRecord;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.impl.BaseLightningPoint;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.impl.LightningPulsePoint;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.impl.LightningStrikePoint;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgMsgType;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgPulseType;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgStrikeType;
|
||||
import com.raytheon.uf.common.numeric.UnsignedNumbers;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.time.util.TimeUtil;
|
||||
import com.raytheon.uf.common.wmo.WMOHeader;
|
||||
|
||||
/**
|
||||
* Decoder for Earth Networks Total Lightning data
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* May 30, 2014 3226 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public class TotalLightningDecoder {
|
||||
|
||||
// flash types
|
||||
public static final byte CLOUD_TO_GROUND_TYPE = 0x00;
|
||||
|
||||
public static final byte CLOUD_TO_CLOUD_TYPE = 0x01;
|
||||
|
||||
// pulse types
|
||||
public static final byte RETURN_STROKE_TYPE = 0x00;
|
||||
|
||||
public static final byte NON_RETURN_STROKE_TYPE = 0x01;
|
||||
|
||||
public static final byte KEEP_ALIVE_TYPE = 0x09;
|
||||
|
||||
// conversions
|
||||
public static final double LONLAT_SCALE_FACTOR = 0.0000001;
|
||||
|
||||
public static final double AMPS_PER_KILO_AMP = 1000.0;
|
||||
|
||||
public static final double METERS_PER_KILOMETER = 1000.0;
|
||||
|
||||
// constant metadata
|
||||
public static final String DATA_SOURCE = "ENTLN";
|
||||
|
||||
private static final IUFStatusHandler log = UFStatus
|
||||
.getHandler(TotalLightningDecoder.class);
|
||||
|
||||
/**
|
||||
* Parse total lightning data into BinLightningRecords
|
||||
*
|
||||
* @param data
|
||||
* @param headers
|
||||
* @return
|
||||
*/
|
||||
public PluginDataObject[] decode(byte[] data, Headers headers) {
|
||||
PluginDataObject[] rval;
|
||||
WMOHeader wmoHdr = new WMOHeader(data);
|
||||
String fileName = (String) headers.get(WMOHeader.INGEST_FILE_NAME);
|
||||
if (wmoHdr.isValid()) {
|
||||
byte[] pdata = BinLightningDecoder.extractPData(wmoHdr, data);
|
||||
if (pdata != null) {
|
||||
try {
|
||||
rval = decodeInternal(fileName, pdata);
|
||||
} catch (Exception e) {
|
||||
error(e, headers, wmoHdr);
|
||||
rval = new PluginDataObject[0];
|
||||
}
|
||||
} else {
|
||||
warn("Unable to separate data from headers", fileName, wmoHdr);
|
||||
rval = new PluginDataObject[0];
|
||||
}
|
||||
} else {
|
||||
warn("Invalid WMO header", fileName, wmoHdr);
|
||||
rval = new PluginDataObject[0];
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display warning message with file and header names
|
||||
*
|
||||
* @param msg
|
||||
* @param fileName
|
||||
* @param wmoHdr
|
||||
*/
|
||||
private void warn(String msg, String fileName, WMOHeader wmoHdr) {
|
||||
log.warn(msg + ". File: " + fileName + ", WMO Header: " + wmoHdr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display error message with file and header names
|
||||
*
|
||||
* @param e
|
||||
* @param headers
|
||||
* @param wmoHdr
|
||||
*/
|
||||
private void error(Exception e, Headers headers, WMOHeader wmoHdr) {
|
||||
String fileName = (String) headers.get(WMOHeader.INGEST_FILE_NAME);
|
||||
log.error(e.getLocalizedMessage() + ". File: " + fileName
|
||||
+ ", WMO Header: " + wmoHdr, e);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param fileName
|
||||
* @param pdata
|
||||
* data after WMO header is removed
|
||||
* @return
|
||||
* @throws DecoderException
|
||||
*/
|
||||
private PluginDataObject[] decodeInternal(String fileName, byte[] pdata)
|
||||
throws DecoderException {
|
||||
List<LightningStrikePoint> decodeStrikes = decodeStrikes(fileName,
|
||||
pdata);
|
||||
BinLightningRecord record = new BinLightningRecord(decodeStrikes);
|
||||
return new PluginDataObject[] { record };
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extract strike data from raw binary
|
||||
*
|
||||
* @param fileName
|
||||
* @param pdata
|
||||
* @return
|
||||
* @throws DecoderException
|
||||
*/
|
||||
private List<LightningStrikePoint> decodeStrikes(String fileName,
|
||||
byte[] pdata) throws DecoderException {
|
||||
List<LightningStrikePoint> rval = new ArrayList<LightningStrikePoint>();
|
||||
ChecksumByteBuffer buff = new ChecksumByteBuffer(pdata);
|
||||
while (buff.position() < buff.size()) {
|
||||
int totalBytes = UnsignedNumbers.ushortToInt(buff.getShort());
|
||||
if (totalBytes > (buff.size() - buff.position())) {
|
||||
log.error("Truncated total lightning packet in file: "
|
||||
+ fileName);
|
||||
break;
|
||||
}
|
||||
/* start flash packet */
|
||||
buff.resetPacketSum();
|
||||
/* discard flash packet size byte */
|
||||
buff.get();
|
||||
|
||||
LtgStrikeType flashType = getStrikeType(buff.get());
|
||||
LightningStrikePoint strike = new LightningStrikePoint(null,
|
||||
LtgMsgType.TOTAL_LIGHTNING);
|
||||
strike.setLightSource(DATA_SOURCE);
|
||||
strike.setType(flashType);
|
||||
decodeCommonFields(strike, buff);
|
||||
|
||||
int pulseCount = UnsignedNumbers.ubyteToShort(buff.get());
|
||||
strike.setPulseCount(pulseCount);
|
||||
checkSum(buff, false);
|
||||
|
||||
List<LightningPulsePoint> pulses = new ArrayList<LightningPulsePoint>(
|
||||
pulseCount);
|
||||
for (int i = 0; i < pulseCount; ++i) {
|
||||
/* discard size of pulse packet (always 26) */
|
||||
buff.get();
|
||||
LtgPulseType pulseType = getPulseType(buff.get());
|
||||
LightningPulsePoint pulse = new LightningPulsePoint(null,
|
||||
pulseType);
|
||||
decodeCommonFields(pulse, buff);
|
||||
/* discard pulse count (already set in strike) */
|
||||
buff.get();
|
||||
checkSum(buff, false);
|
||||
pulses.add(pulse);
|
||||
}
|
||||
strike.setPulses(pulses);
|
||||
checkSum(buff, true);
|
||||
rval.add(strike);
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract fields common to both strikes and pulses
|
||||
*
|
||||
* @param point
|
||||
* @param buff
|
||||
*/
|
||||
private static void decodeCommonFields(BaseLightningPoint point,
|
||||
ChecksumByteBuffer buff) {
|
||||
point.setTime(getTime(buff));
|
||||
point.setLatitude(getDouble(buff, LONLAT_SCALE_FACTOR));
|
||||
point.setLongitude(getDouble(buff, LONLAT_SCALE_FACTOR));
|
||||
point.setStrikeStrength(getKiloAmps(buff.getInt()));
|
||||
/* discard reserved byte */
|
||||
buff.get();
|
||||
point.setElevation(getMeters(buff.getShort()));
|
||||
point.setSensorCount(UnsignedNumbers.ubyteToShort(buff.get()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create calendar from 4 byte UNIX time and 2 byte millisecond addition
|
||||
*
|
||||
* @param buff
|
||||
* @return
|
||||
*/
|
||||
private static Calendar getTime(ChecksumByteBuffer buff) {
|
||||
long unixTime = UnsignedNumbers.uintToLong(buff.getInt());
|
||||
int additionalMillis = UnsignedNumbers.ushortToInt(buff.getShort());
|
||||
long totalMillis = (unixTime * TimeUtil.MILLIS_PER_SECOND)
|
||||
+ additionalMillis;
|
||||
return TimeUtil.newGmtCalendar(new Date(totalMillis));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure data integrity, resets appropriate sum(s) in buffer after check
|
||||
*
|
||||
* @param buff
|
||||
* @param total
|
||||
* true if total sum should be checked, otherwise checks packet
|
||||
* sum
|
||||
* @throws DecoderException
|
||||
* if check fails
|
||||
*/
|
||||
private static void checkSum(ChecksumByteBuffer buff, boolean total)
|
||||
throws DecoderException {
|
||||
long rawsum = total ? buff.getTotalSum() : buff.getPacketSum();
|
||||
/* convert to overflowed unsigned byte */
|
||||
rawsum &= 0xFF;
|
||||
/* checksum algorithm from total lightning spec */
|
||||
long mungedSum = (256 - rawsum) & 0xFF;
|
||||
/* get expected after sum so it is not reflected in sum */
|
||||
long expected = UnsignedNumbers.ubyteToShort(buff.get());
|
||||
if (mungedSum != expected) {
|
||||
throw new DecoderException("Checksum failed: expected " + expected
|
||||
+ " got " + mungedSum);
|
||||
}
|
||||
if (total) {
|
||||
buff.resetAllSums();
|
||||
} else {
|
||||
buff.resetPacketSum();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get scaled double from 4 byte integer field
|
||||
*
|
||||
* @param buff
|
||||
* @param scaleFactor
|
||||
* @return
|
||||
*/
|
||||
private static double getDouble(ChecksumByteBuffer buff, double scaleFactor) {
|
||||
int raw = buff.getInt();
|
||||
return raw * scaleFactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert amps to kiloamps
|
||||
*
|
||||
* @param amps
|
||||
* @return
|
||||
*/
|
||||
private static double getKiloAmps(int amps) {
|
||||
return amps / AMPS_PER_KILO_AMP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert kilometers to meters
|
||||
*
|
||||
* @param kilometers
|
||||
* @return
|
||||
*/
|
||||
private static double getMeters(short kilometers) {
|
||||
return kilometers * METERS_PER_KILOMETER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map strike byte to internal enum
|
||||
*
|
||||
* @param type
|
||||
* @return
|
||||
* @throws DecoderException
|
||||
*/
|
||||
public static LtgStrikeType getStrikeType(byte type)
|
||||
throws DecoderException {
|
||||
switch (type) {
|
||||
case CLOUD_TO_GROUND_TYPE:
|
||||
return LtgStrikeType.CLOUD_TO_GROUND;
|
||||
case CLOUD_TO_CLOUD_TYPE:
|
||||
return LtgStrikeType.CLOUD_TO_CLOUD;
|
||||
case KEEP_ALIVE_TYPE:
|
||||
return LtgStrikeType.KEEP_ALIVE;
|
||||
}
|
||||
throw new DecoderException("Unknown flash type: " + type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map pulse byte to internal enum
|
||||
*
|
||||
* @param type
|
||||
* @return
|
||||
* @throws DecoderException
|
||||
*/
|
||||
public static LtgPulseType getPulseType(byte type) throws DecoderException {
|
||||
switch (type) {
|
||||
case RETURN_STROKE_TYPE:
|
||||
return LtgPulseType.RETURN_STROKE;
|
||||
case NON_RETURN_STROKE_TYPE:
|
||||
return LtgPulseType.NON_RETURN_STROKE;
|
||||
case KEEP_ALIVE_TYPE:
|
||||
return LtgPulseType.KEEP_ALIVE;
|
||||
}
|
||||
throw new DecoderException("Unknown pulse type: " + type);
|
||||
}
|
||||
|
||||
}
|
|
@ -20,5 +20,5 @@
|
|||
-->
|
||||
<requestPatterns xmlns:ns2="group">
|
||||
<regex>^SFUS41 KWBC.*</regex>
|
||||
<regex>^SFPA41 KWBC.*</regex>
|
||||
<regex>^SFPA4[12] KWBC.*</regex>
|
||||
</requestPatterns>
|
||||
|
|
|
@ -29,11 +29,7 @@ import com.raytheon.edex.plugin.textlightning.impl.TextLightningParser;
|
|||
import com.raytheon.uf.common.dataplugin.PluginDataObject;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.BinLightningRecord;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.impl.LightningStrikePoint;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.common.time.DataTime;
|
||||
import com.raytheon.uf.common.time.TimeRange;
|
||||
import com.raytheon.uf.edex.decodertools.time.TimeTools;
|
||||
import com.raytheon.uf.common.time.util.TimeUtil;
|
||||
|
||||
/**
|
||||
* Decoder for text lightning data
|
||||
|
@ -47,6 +43,7 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools;
|
|||
* Mar 25, 2010 jsanchez Initial creation
|
||||
* Aug 30, 2013 2298 rjpeter Make getPluginName abstract
|
||||
* Feb 12, 2014 2655 njensen Set source
|
||||
* Jun 05, 2014 3226 bclement LightningStikePoint refactor
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -57,9 +54,6 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools;
|
|||
public class TextLightningDecoder extends AbstractDecoder implements
|
||||
IBinaryDecoder {
|
||||
|
||||
private static final IUFStatusHandler logger = UFStatus
|
||||
.getHandler(TextLightningDecoder.class);
|
||||
|
||||
private String traceId = null;
|
||||
|
||||
/**
|
||||
|
@ -92,37 +86,19 @@ public class TextLightningDecoder extends AbstractDecoder implements
|
|||
BinLightningRecord report = null;
|
||||
|
||||
if (strikes.size() > 0) {
|
||||
report = new BinLightningRecord(strikes.size());
|
||||
for (LightningStrikePoint strike : strikes) {
|
||||
report.addStrike(strike);
|
||||
logger.debug(traceId + "-" + strike);
|
||||
}
|
||||
report = new BinLightningRecord(strikes);
|
||||
} else {
|
||||
return new PluginDataObject[0];
|
||||
}
|
||||
|
||||
Calendar c = TimeTools.getSystemCalendar();
|
||||
if (c == null) {
|
||||
throw new DecoderException(traceId + "-Error decoding times");
|
||||
}
|
||||
Calendar c = TimeUtil.newGmtCalendar();
|
||||
report.setInsertTime(c);
|
||||
|
||||
Calendar cStart = report.getStartTime();
|
||||
Calendar cStop = report.getStopTime();
|
||||
report.setTraceId(traceId);
|
||||
|
||||
TimeRange range = new TimeRange(cStart.getTimeInMillis(),
|
||||
cStop.getTimeInMillis());
|
||||
|
||||
DataTime dataTime = new DataTime(cStart, range);
|
||||
report.setDataTime(dataTime);
|
||||
|
||||
if (report != null) {
|
||||
report.setTraceId(traceId);
|
||||
|
||||
// TODO anyone have any idea what the source should actually be
|
||||
// named?
|
||||
report.setSource("text");
|
||||
}
|
||||
// TODO anyone have any idea what the source should actually be
|
||||
// named?
|
||||
report.setSource("text");
|
||||
|
||||
return new PluginDataObject[] { report };
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ import com.raytheon.uf.common.status.UFStatus.Priority;
|
|||
* lgtng intensities -999 to
|
||||
* 999
|
||||
* Feb 12, 2014 2655 njensen Use status handler for logging
|
||||
* Jun 05, 2014 3226 bclement LightningStikePoint refactor
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -177,7 +178,7 @@ public class TextLightningParser {
|
|||
Double.parseDouble(latitude),
|
||||
Double.parseDouble(longitude));
|
||||
strike.setStrikeStrength(Double.parseDouble(strength));
|
||||
strike.setStrikeCount(Integer.parseInt(count));
|
||||
strike.setPulseCount(Integer.parseInt(count));
|
||||
strike.setMonth(Integer.parseInt(month));
|
||||
strike.setDay(Integer.parseInt(day));
|
||||
strike.setYear(Integer.parseInt(year));
|
||||
|
@ -186,7 +187,7 @@ public class TextLightningParser {
|
|||
strike.setSecond(Integer.parseInt(sec));
|
||||
strike.setMillis(0);
|
||||
strike.setMsgType(LtgMsgType.STRIKE_MSG_FL);
|
||||
strike.setType(LtgStrikeType.STRIKE_CG);
|
||||
strike.setType(LtgStrikeType.CLOUD_TO_GROUND);
|
||||
strike.setLightSource("UNKN");
|
||||
reports.add(strike);
|
||||
} else {
|
||||
|
@ -214,7 +215,7 @@ public class TextLightningParser {
|
|||
Double.parseDouble(latitude), lon);
|
||||
strike.setStrikeStrength(Double
|
||||
.parseDouble(strength));
|
||||
strike.setStrikeCount(Integer.parseInt(count));
|
||||
strike.setPulseCount(Integer.parseInt(count));
|
||||
strike.setMonth(Integer.parseInt(month));
|
||||
strike.setDay(Integer.parseInt(day));
|
||||
strike.setYear(Integer.parseInt(year) + 2000);
|
||||
|
@ -223,7 +224,7 @@ public class TextLightningParser {
|
|||
strike.setSecond(Integer.parseInt(sec));
|
||||
strike.setMillis(Integer.parseInt(msec) * 10);
|
||||
strike.setMsgType(LtgMsgType.STRIKE_MSG_FL);
|
||||
strike.setType(LtgStrikeType.STRIKE_CG);
|
||||
strike.setType(LtgStrikeType.CLOUD_TO_GROUND);
|
||||
strike.setLightSource("UNKN");
|
||||
reports.add(strike);
|
||||
} else {
|
||||
|
@ -250,7 +251,7 @@ public class TextLightningParser {
|
|||
Double.parseDouble(longitude));
|
||||
strike.setStrikeStrength(Double
|
||||
.parseDouble(strength));
|
||||
strike.setStrikeCount(Integer.parseInt(count));
|
||||
strike.setPulseCount(Integer.parseInt(count));
|
||||
strike.setMonth(Integer.parseInt(month));
|
||||
strike.setDay(Integer.parseInt(day));
|
||||
strike.setYear(Integer.parseInt(year));
|
||||
|
@ -259,7 +260,7 @@ public class TextLightningParser {
|
|||
strike.setSecond(Integer.parseInt(sec));
|
||||
strike.setMillis(Integer.parseInt(msec) * 10);
|
||||
strike.setMsgType(LtgMsgType.STRIKE_MSG_FL);
|
||||
strike.setType(LtgStrikeType.STRIKE_CG);
|
||||
strike.setType(LtgStrikeType.CLOUD_TO_GROUND);
|
||||
strike.setLightSource(sls);
|
||||
reports.add(strike);
|
||||
} else {
|
||||
|
|
|
@ -19,8 +19,13 @@
|
|||
**/
|
||||
package com.raytheon.uf.common.dataplugin.binlightning;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
|
@ -35,18 +40,17 @@ import org.hibernate.annotations.Index;
|
|||
|
||||
import com.raytheon.uf.common.dataplugin.PluginDataObject;
|
||||
import com.raytheon.uf.common.dataplugin.annotations.DataURI;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.impl.LightningPulsePoint;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.impl.LightningStrikePoint;
|
||||
import com.raytheon.uf.common.dataplugin.persist.IPersistable;
|
||||
import com.raytheon.uf.common.dataplugin.persist.PersistablePluginDataObject;
|
||||
import com.raytheon.uf.common.datastorage.IDataStore;
|
||||
import com.raytheon.uf.common.datastorage.StorageException;
|
||||
import com.raytheon.uf.common.datastorage.records.ByteDataRecord;
|
||||
import com.raytheon.uf.common.datastorage.records.FloatDataRecord;
|
||||
import com.raytheon.uf.common.datastorage.records.IDataRecord;
|
||||
import com.raytheon.uf.common.datastorage.records.IntegerDataRecord;
|
||||
import com.raytheon.uf.common.datastorage.records.LongDataRecord;
|
||||
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
|
||||
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
|
||||
import com.raytheon.uf.common.time.DataTime;
|
||||
import com.raytheon.uf.common.time.TimeRange;
|
||||
import com.raytheon.uf.common.time.util.TimeUtil;
|
||||
|
||||
/**
|
||||
|
@ -82,6 +86,8 @@ import com.raytheon.uf.common.time.util.TimeUtil;
|
|||
* Oct 22, 2013 2361 njensen Removed XML annotations
|
||||
* Jan 21, 2014 2667 bclement renamed record's lightSource field to source
|
||||
* May 14, 2014 2536 bclement removed TimeTools usage
|
||||
* Jun 05, 2014 3226 bclement moved data arrays into map for easier management
|
||||
* replaced addStrike() with List constructor, added pulses
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -106,43 +112,12 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
|
|||
|
||||
public static final String PLUGIN_NAME = "binlightning";
|
||||
|
||||
// Data store data items
|
||||
@Transient
|
||||
private long[] obsTimes = null;
|
||||
private final Map<String, Object> strikeDataArrays = new TreeMap<String, Object>();
|
||||
|
||||
@Transient
|
||||
private float[] latitudes = null;
|
||||
|
||||
@Transient
|
||||
private float[] longitudes = null;
|
||||
|
||||
@Transient
|
||||
private int[] intensities = null;
|
||||
|
||||
@Transient
|
||||
private byte[] msgTypes = null;
|
||||
|
||||
@Transient
|
||||
private byte[] strikeTypes = null;
|
||||
|
||||
@Transient
|
||||
private byte[] strikeCounts = null;
|
||||
|
||||
@Transient
|
||||
private Object[] dataArrays = null;
|
||||
|
||||
// Data store data item names
|
||||
@Transient
|
||||
private final String[] dataNames = { "obsTime", "latitude", "longitude",
|
||||
"intensity", "msgType", "strikeType", "strikeCount", };
|
||||
|
||||
@Transient
|
||||
private int insertIndex = 0;
|
||||
|
||||
@Transient
|
||||
private long startTimeMillis = Long.MAX_VALUE;
|
||||
|
||||
@Transient
|
||||
private long stopTimeMillis = Long.MIN_VALUE;
|
||||
private final Map<String, Object> pulseDataArrays = new TreeMap<String, Object>();
|
||||
|
||||
// Persisted value - Earliest strike time in the collection.
|
||||
@DataURI(position = 1)
|
||||
|
@ -177,63 +152,148 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
|
|||
*
|
||||
* @param uri
|
||||
* The dataURI
|
||||
* @param tableDef
|
||||
* The table definition associated with this class
|
||||
*/
|
||||
public BinLightningRecord(String uri) {
|
||||
super(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an empty lightning record.
|
||||
* Construct a lightning record from a list of strikes
|
||||
*
|
||||
* @param strikes
|
||||
*/
|
||||
public BinLightningRecord(int arraysSize) {
|
||||
obsTimes = new long[arraysSize];
|
||||
latitudes = new float[arraysSize];
|
||||
longitudes = new float[arraysSize];
|
||||
public BinLightningRecord(final List<LightningStrikePoint> strikes) {
|
||||
final int arraysSize = strikes.size();
|
||||
long[] obsTimes = new long[arraysSize];
|
||||
float[] latitudes = new float[arraysSize];
|
||||
float[] longitudes = new float[arraysSize];
|
||||
int[] intensities = new int[arraysSize];
|
||||
byte[] msgTypes = new byte[arraysSize];
|
||||
byte[] strikeTypes = new byte[arraysSize];
|
||||
byte[] pulseCounts = new byte[arraysSize];
|
||||
int[] pulseIndexes = new int[arraysSize];
|
||||
int[] heights = new int[arraysSize];
|
||||
int[] sensorCounts = new int[arraysSize];
|
||||
|
||||
intensities = new int[arraysSize];
|
||||
msgTypes = new byte[arraysSize];
|
||||
strikeTypes = new byte[arraysSize];
|
||||
strikeCounts = new byte[arraysSize];
|
||||
dataArrays = new Object[] { obsTimes, latitudes, longitudes,
|
||||
intensities, msgTypes, strikeTypes, strikeCounts, };
|
||||
insertIndex = 0;
|
||||
strikeDataArrays.put(LightningConstants.TIME_DATASET, obsTimes);
|
||||
strikeDataArrays.put(LightningConstants.LAT_DATASET, latitudes);
|
||||
strikeDataArrays.put(LightningConstants.LON_DATASET, longitudes);
|
||||
strikeDataArrays.put(LightningConstants.INTENSITY_DATASET, intensities);
|
||||
strikeDataArrays.put(LightningConstants.MSG_TYPE_DATASET, msgTypes);
|
||||
strikeDataArrays.put(LightningConstants.STRIKE_TYPE_DATASET,
|
||||
strikeTypes);
|
||||
strikeDataArrays
|
||||
.put(LightningConstants.PULSE_COUNT_DATSET, pulseCounts);
|
||||
strikeDataArrays.put(LightningConstants.PULSE_INDEX_DATASET,
|
||||
pulseIndexes);
|
||||
strikeDataArrays.put(LightningConstants.HEIGHT_DATASET, heights);
|
||||
strikeDataArrays.put(LightningConstants.SENSOR_COUNT_DATASET,
|
||||
sensorCounts);
|
||||
|
||||
if (arraysSize > 0) {
|
||||
LightningStrikePoint sample = strikes.get(0);
|
||||
setDataSource(sample);
|
||||
}
|
||||
|
||||
long startTimeMillis = Long.MAX_VALUE;
|
||||
long stopTimeMillis = Long.MIN_VALUE;
|
||||
|
||||
int pulseDataCount = 0;
|
||||
|
||||
final Iterator<LightningStrikePoint> iter = strikes.iterator();
|
||||
for (int i = 0; i < arraysSize; ++i) {
|
||||
LightningStrikePoint strike = iter.next();
|
||||
Calendar c = strike.getTime();
|
||||
|
||||
long obsTimeMillis = c.getTimeInMillis();
|
||||
|
||||
startTimeMillis = Math.min(startTimeMillis, obsTimeMillis);
|
||||
stopTimeMillis = Math.max(stopTimeMillis, obsTimeMillis);
|
||||
|
||||
obsTimes[i] = obsTimeMillis;
|
||||
latitudes[i] = (float) strike.getLatitude();
|
||||
longitudes[i] = (float) strike.getLongitude();
|
||||
|
||||
intensities[i] = (int) Math.round(strike.getStrikeStrength());
|
||||
msgTypes[i] = (byte) strike.getMsgType().getId();
|
||||
strikeTypes[i] = (byte) strike.getType().getId();
|
||||
/* some types have pulse counts but no pulse data */
|
||||
pulseCounts[i] = (byte) strike.getPulseCount();
|
||||
heights[i] = (int) Math.round(strike.getElevation());
|
||||
sensorCounts[i] = strike.getSensorCount();
|
||||
|
||||
List<LightningPulsePoint> pulses = strike.getPulses();
|
||||
if (pulses != null && !pulses.isEmpty()) {
|
||||
pulseIndexes[i] = pulseDataCount;
|
||||
pulseDataCount += pulses.size();
|
||||
if (pulseCounts[i] != pulses.size()) {
|
||||
pulseCounts[i] = (byte) pulses.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pulseDataCount > 0) {
|
||||
/* at least one of the strikes had pulse data */
|
||||
setPulseData(strikes, pulseDataCount);
|
||||
}
|
||||
startTime = TimeUtil.newGmtCalendar(new Date(startTimeMillis));
|
||||
stopTime = TimeUtil.newGmtCalendar(new Date(stopTimeMillis));
|
||||
|
||||
TimeRange range = new TimeRange(startTime, stopTime);
|
||||
setDataTime(new DataTime(startTime, range));
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Construct an empty lightning record.
|
||||
// *
|
||||
// * @param message
|
||||
// * Lightning data report.
|
||||
// */
|
||||
// public BinLightningRecord(String message) {
|
||||
// super(message);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Track the current persistence time for the data set.
|
||||
* @param strikes
|
||||
* @param pulseDataCount
|
||||
* total number of pulses for all strikes
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private void updatePersistenceTime() {
|
||||
if ((startTimeMillis != Long.MAX_VALUE)
|
||||
&& (stopTimeMillis != Long.MIN_VALUE)) {
|
||||
persistTime = (startTimeMillis + stopTimeMillis) / 2;
|
||||
setPersistenceTime(new Date(persistTime));
|
||||
} else {
|
||||
setPersistenceTime(TimeUtil.newGmtCalendar().getTime());
|
||||
persistTime = getInsertTime().getTimeInMillis();
|
||||
private void setPulseData(final List<LightningStrikePoint> strikes,
|
||||
final int pulseDataCount) {
|
||||
long[] pulseTimes = new long[pulseDataCount];
|
||||
float[] pulseLats = new float[pulseDataCount];
|
||||
float[] pulseLons = new float[pulseDataCount];
|
||||
int[] pulseIntensities = new int[pulseDataCount];
|
||||
byte[] pulseTypes = new byte[pulseDataCount];
|
||||
int[] pulseHeights = new int[pulseDataCount];
|
||||
int[] pulseSensorCounts = new int[pulseDataCount];
|
||||
|
||||
pulseDataArrays.put(LightningConstants.TIME_DATASET, pulseTimes);
|
||||
pulseDataArrays.put(LightningConstants.LAT_DATASET, pulseLats);
|
||||
pulseDataArrays.put(LightningConstants.LON_DATASET, pulseLons);
|
||||
pulseDataArrays.put(LightningConstants.INTENSITY_DATASET,
|
||||
pulseIntensities);
|
||||
pulseDataArrays.put(LightningConstants.PULSE_TYPE_DATASET, pulseTypes);
|
||||
pulseDataArrays.put(LightningConstants.HEIGHT_DATASET, pulseHeights);
|
||||
pulseDataArrays.put(LightningConstants.SENSOR_COUNT_DATASET,
|
||||
pulseSensorCounts);
|
||||
|
||||
int index = 0;
|
||||
for (LightningStrikePoint strike : strikes) {
|
||||
List<LightningPulsePoint> pulses = strike.getPulses();
|
||||
if (pulses != null && !pulses.isEmpty()) {
|
||||
for (LightningPulsePoint pulse : pulses) {
|
||||
pulseTimes[index] = pulse.getTime().getTimeInMillis();
|
||||
pulseLats[index] = (float) pulse.getLatitude();
|
||||
pulseLons[index] = (float) pulse.getLongitude();
|
||||
pulseIntensities[index] = (int) Math.round(pulse
|
||||
.getStrikeStrength());
|
||||
pulseTypes[index] = pulse.getType().getId();
|
||||
pulseHeights[index] = (int) Math
|
||||
.round(pulse.getElevation());
|
||||
pulseSensorCounts[index] = pulse.getSensorCount();
|
||||
++index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a strike report to the record collection.
|
||||
* Extract data source from strike
|
||||
*
|
||||
* @param strike
|
||||
* A strike report to add.
|
||||
*/
|
||||
public void addStrike(LightningStrikePoint strike) {
|
||||
// jjg add
|
||||
private void setDataSource(LightningStrikePoint strike) {
|
||||
if (source == null) {
|
||||
if (strike.getLightSource() == null) {
|
||||
source = "NLDN";
|
||||
|
@ -249,47 +309,6 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
|
|||
source = "UNKN";
|
||||
}
|
||||
}
|
||||
// end
|
||||
|
||||
if (insertIndex < obsTimes.length) {
|
||||
long t1 = startTimeMillis;
|
||||
|
||||
Calendar c = TimeUtil.newGmtCalendar(strike.getYear(),
|
||||
strike.getMonth(), strike.getDay());
|
||||
|
||||
c.set(Calendar.HOUR_OF_DAY, strike.getHour());
|
||||
c.set(Calendar.MINUTE, strike.getMinute());
|
||||
c.set(Calendar.SECOND, strike.getSecond());
|
||||
c.set(Calendar.MILLISECOND, strike.getMillis());
|
||||
|
||||
long obsTimeMillis = c.getTimeInMillis();
|
||||
|
||||
startTimeMillis = Math.min(startTimeMillis, obsTimeMillis);
|
||||
stopTimeMillis = Math.max(stopTimeMillis, obsTimeMillis);
|
||||
|
||||
obsTimes[insertIndex] = obsTimeMillis;
|
||||
latitudes[insertIndex] = (float) strike.getLatitude();
|
||||
longitudes[insertIndex] = (float) strike.getLongitude();
|
||||
|
||||
intensities[insertIndex] = Math.round((float) strike
|
||||
.getStrikeStrength());
|
||||
msgTypes[insertIndex] = (byte) strike.getMsgType().ordinal();
|
||||
strikeTypes[insertIndex] = (byte) strike.getType().ordinal();
|
||||
strikeCounts[insertIndex] = (byte) strike.getStrikeCount();
|
||||
insertIndex++;
|
||||
// only update the times if they have changed!
|
||||
if (t1 != startTimeMillis) {
|
||||
startTime = TimeUtil.newGmtCalendar(new Date(startTimeMillis));
|
||||
}
|
||||
if (t1 != stopTimeMillis) {
|
||||
stopTime = TimeUtil.newGmtCalendar(new Date(stopTimeMillis));
|
||||
}
|
||||
|
||||
// updatePersistenceTime();
|
||||
} else {
|
||||
throw new ArrayIndexOutOfBoundsException(String.format(
|
||||
"index greater than length [%d]", insertIndex));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -349,25 +368,14 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
|
|||
setInsertTime(insert_time);
|
||||
}
|
||||
|
||||
public String[] getDataNames() {
|
||||
return dataNames;
|
||||
}
|
||||
|
||||
public Object[] getDataArrays() {
|
||||
return dataArrays;
|
||||
}
|
||||
|
||||
public void setDataArrays(Object[] dataArrays) {
|
||||
this.dataArrays = dataArrays;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the obsTimes
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public long[] getObsTimes() {
|
||||
return obsTimes;
|
||||
Object obj = strikeDataArrays.get(LightningConstants.TIME_DATASET);
|
||||
return obj != null ? (long[]) obj : new long[0];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -376,7 +384,8 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
|
|||
* @return
|
||||
*/
|
||||
public float[] getLatitudes() {
|
||||
return latitudes;
|
||||
Object obj = strikeDataArrays.get(LightningConstants.LAT_DATASET);
|
||||
return obj != null ? (float[]) obj : new float[0];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -385,7 +394,8 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
|
|||
* @return
|
||||
*/
|
||||
public float[] getLongitudes() {
|
||||
return longitudes;
|
||||
Object obj = strikeDataArrays.get(LightningConstants.LON_DATASET);
|
||||
return obj != null ? (float[]) obj : new float[0];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -394,7 +404,8 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
|
|||
* @return
|
||||
*/
|
||||
public int[] getIntensities() {
|
||||
return intensities;
|
||||
Object obj = strikeDataArrays.get(LightningConstants.INTENSITY_DATASET);
|
||||
return obj != null ? (int[]) obj : new int[0];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -403,7 +414,8 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
|
|||
* @return
|
||||
*/
|
||||
public byte[] getMsgTypes() {
|
||||
return msgTypes;
|
||||
Object obj = strikeDataArrays.get(LightningConstants.MSG_TYPE_DATASET);
|
||||
return obj != null ? (byte[]) obj : new byte[0];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -412,7 +424,9 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
|
|||
* @return
|
||||
*/
|
||||
public byte[] getStrikeTypes() {
|
||||
return strikeTypes;
|
||||
Object obj = strikeDataArrays
|
||||
.get(LightningConstants.STRIKE_TYPE_DATASET);
|
||||
return obj != null ? (byte[]) obj : new byte[0];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -420,8 +434,10 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
public byte[] getStrikeCounts() {
|
||||
return strikeCounts;
|
||||
public byte[] getPulseCounts() {
|
||||
Object obj = strikeDataArrays
|
||||
.get(LightningConstants.PULSE_COUNT_DATSET);
|
||||
return obj != null ? (byte[]) obj : new byte[0];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -449,42 +465,55 @@ public class BinLightningRecord extends PersistablePluginDataObject implements
|
|||
*/
|
||||
public void retrieveFromDataStore(IDataStore dataStore)
|
||||
throws StorageException {
|
||||
retrieveFromDataStore(dataStore, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data arrays from the store.
|
||||
*
|
||||
* @param dataStore
|
||||
* @param includePulses
|
||||
* extract pulse data if true
|
||||
*/
|
||||
public void retrieveFromDataStore(IDataStore dataStore,
|
||||
boolean includePulses) throws StorageException {
|
||||
try {
|
||||
IDataRecord[] dataRec = dataStore.retrieve(getDataURI());
|
||||
dataArrays = new Object[dataRec.length];
|
||||
for (int i = 0; i < dataRec.length; i++) {
|
||||
if (dataRec[i].getName().equals("obsTime")) {
|
||||
obsTimes = ((LongDataRecord) dataRec[i]).getLongData();
|
||||
dataArrays[i] = obsTimes;
|
||||
}
|
||||
if (dataRec[i].getName().equals("latitude")) {
|
||||
latitudes = ((FloatDataRecord) dataRec[i]).getFloatData();
|
||||
dataArrays[i] = latitudes;
|
||||
} else if (dataRec[i].getName().equals("longitude")) {
|
||||
longitudes = ((FloatDataRecord) dataRec[i]).getFloatData();
|
||||
dataArrays[i] = longitudes;
|
||||
} else if (dataRec[i].getName().equals("intensity")) {
|
||||
intensities = ((IntegerDataRecord) dataRec[i]).getIntData();
|
||||
dataArrays[i] = intensities;
|
||||
} else if (dataRec[i].getName().equals("msgType")) {
|
||||
msgTypes = ((ByteDataRecord) dataRec[i]).getByteData();
|
||||
dataArrays[i] = msgTypes;
|
||||
} else if (dataRec[i].getName().equals("strikeType")) {
|
||||
strikeTypes = ((ByteDataRecord) dataRec[i]).getByteData();
|
||||
dataArrays[i] = strikeTypes;
|
||||
} else if (dataRec[i].getName().equals("strikeCount")) {
|
||||
strikeCounts = ((ByteDataRecord) dataRec[i]).getByteData();
|
||||
dataArrays[i] = strikeCounts;
|
||||
IDataRecord[] dataRecs = dataStore.retrieve(getDataURI());
|
||||
for (IDataRecord record : dataRecs) {
|
||||
strikeDataArrays.put(record.getName(), record.getDataObject());
|
||||
}
|
||||
if (includePulses) {
|
||||
String pulseGroup = getDataURI() + DataURI.SEPARATOR
|
||||
+ LightningConstants.PULSE_HDF5_GROUP_SUFFIX;
|
||||
try {
|
||||
IDataRecord[] pulseRecords = dataStore.retrieve(pulseGroup);
|
||||
for (IDataRecord record : pulseRecords) {
|
||||
pulseDataArrays.put(record.getName(),
|
||||
record.getDataObject());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
/* FIXME better way to find out if group doesn't exist */
|
||||
}
|
||||
}
|
||||
setDataArrays(dataArrays);
|
||||
|
||||
} catch (Exception se) {
|
||||
se.printStackTrace();
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new StorageException(e.getLocalizedMessage(), null, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the strikeDataArrays
|
||||
*/
|
||||
public Map<String, Object> getStrikeDataArrays() {
|
||||
return strikeDataArrays;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the pulseDataArrays
|
||||
*/
|
||||
public Map<String, Object> getPulseDataArrays() {
|
||||
return pulseDataArrays;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Column
|
||||
@Access(AccessType.PROPERTY)
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* 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 com.raytheon.uf.common.dataplugin.binlightning;
|
||||
|
||||
/**
|
||||
* Constants used for lightning data such as dataset names in HDF5
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* May 30, 2014 3226 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public class LightningConstants {
|
||||
|
||||
public static final String PULSE_HDF5_GROUP_SUFFIX = "pulse";
|
||||
|
||||
// HDF5 dataset names
|
||||
|
||||
public static final String TIME_DATASET = "obsTime";
|
||||
|
||||
public static final String LAT_DATASET = "latitude";
|
||||
|
||||
public static final String LON_DATASET = "longitude";
|
||||
|
||||
public static final String INTENSITY_DATASET = "intensity";
|
||||
|
||||
public static final String MSG_TYPE_DATASET = "msgType";
|
||||
|
||||
public static final String STRIKE_TYPE_DATASET = "strikeType";
|
||||
|
||||
public static final String PULSE_COUNT_DATSET = "pulseCount";
|
||||
|
||||
public static final String PULSE_INDEX_DATASET = "pulseIndex";
|
||||
|
||||
public static final String PULSE_TYPE_DATASET = "pulseType";
|
||||
|
||||
public static final String HEIGHT_DATASET = "height";
|
||||
|
||||
public static final String SENSOR_COUNT_DATASET = "sensorCount";
|
||||
|
||||
}
|
|
@ -0,0 +1,259 @@
|
|||
/**
|
||||
* 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 com.raytheon.uf.common.dataplugin.binlightning.impl;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
import com.raytheon.uf.common.time.util.TimeUtil;
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
|
||||
/**
|
||||
* Lightning information common to strikes and pulses
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 3, 2014 3226 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public class BaseLightningPoint {
|
||||
|
||||
private final Coordinate point;
|
||||
|
||||
private Calendar time;
|
||||
|
||||
// Lightning strike strength and polarity
|
||||
private double strikeStrength;
|
||||
|
||||
private int sensorCount;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public BaseLightningPoint() {
|
||||
this(TimeUtil.newGmtCalendar());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param time
|
||||
*/
|
||||
public BaseLightningPoint(Calendar time) {
|
||||
this(new Coordinate(), time);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param point
|
||||
*/
|
||||
public BaseLightningPoint(Coordinate point, Calendar time) {
|
||||
this.point = point;
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param latitude
|
||||
* @param longitude
|
||||
*/
|
||||
public BaseLightningPoint(double latitude, double longitude, Calendar time) {
|
||||
this(new Coordinate(longitude, latitude), time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the year part of the date.
|
||||
*
|
||||
* @param year
|
||||
* Year.
|
||||
*/
|
||||
public void setYear(int year) {
|
||||
this.time.set(Calendar.YEAR, year);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the day of the month part of the date.
|
||||
*
|
||||
* @param day
|
||||
* Day of month [1..12].
|
||||
*/
|
||||
public void setMonth(int month) {
|
||||
this.time.set(Calendar.MONTH, month - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the day of the month part of the date.
|
||||
*
|
||||
* @param day
|
||||
* Day of month [1..12].
|
||||
*/
|
||||
public void setDay(int day) {
|
||||
this.time.set(Calendar.DAY_OF_MONTH, day);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the hour part of the time.
|
||||
*
|
||||
* @param hour
|
||||
* Hour of the day [0..23].
|
||||
*/
|
||||
public void setHour(int hour) {
|
||||
this.time.set(Calendar.HOUR, hour);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the minute of the hour.
|
||||
*
|
||||
* @param minute
|
||||
* The minute of the hour [0..59]
|
||||
*/
|
||||
public void setMinute(int minute) {
|
||||
this.time.set(Calendar.MINUTE, minute);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the second of the minute.
|
||||
*
|
||||
* @param second
|
||||
* The second of the minute [0..59]
|
||||
*/
|
||||
public void setSecond(int second) {
|
||||
this.time.set(Calendar.SECOND, second);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the milliseconds part of the time.
|
||||
*
|
||||
* @param millis
|
||||
* Milliseconds [0..999].
|
||||
*/
|
||||
public void setMillis(int millis) {
|
||||
this.time.set(Calendar.MILLISECOND, millis);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the time
|
||||
*/
|
||||
public Calendar getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param time
|
||||
* the time to set
|
||||
*/
|
||||
public void setTime(Calendar time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the strike strength.
|
||||
*
|
||||
* @return The strike strength.
|
||||
*/
|
||||
public double getStrikeStrength() {
|
||||
return strikeStrength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the strike strength.
|
||||
*
|
||||
* @return The strike strength.
|
||||
*/
|
||||
public void setStrikeStrength(double strikeStrength) {
|
||||
this.strikeStrength = strikeStrength;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the sensorCount
|
||||
*/
|
||||
public int getSensorCount() {
|
||||
return sensorCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sensorCount
|
||||
* the sensorCount to set
|
||||
*/
|
||||
public void setSensorCount(int sensorCount) {
|
||||
this.sensorCount = sensorCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latitude of this point.
|
||||
*
|
||||
* @return The latitude.
|
||||
*/
|
||||
public double getLatitude() {
|
||||
return point.y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the latitude for this point.
|
||||
*
|
||||
* @param latitude
|
||||
* The latitude.
|
||||
*/
|
||||
public void setLatitude(double latitude) {
|
||||
this.point.y = latitude;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the longitude of this point.
|
||||
*
|
||||
* @return The longitude.
|
||||
*/
|
||||
public double getLongitude() {
|
||||
return point.x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the longitude for this point.
|
||||
*
|
||||
* @param longitude
|
||||
* The longitude.
|
||||
*/
|
||||
public void setLongitude(double longitude) {
|
||||
this.point.x = longitude;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the elevation of this point. No units are specified.
|
||||
*
|
||||
* @return The elevation of this point.
|
||||
*/
|
||||
public double getElevation() {
|
||||
return this.point.z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the elevation of this point. No units are specified.
|
||||
*
|
||||
* @param elevation
|
||||
* The elevation of this point.
|
||||
*/
|
||||
public void setElevation(double elevation) {
|
||||
this.point.z = elevation;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* 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 com.raytheon.uf.common.dataplugin.binlightning.impl;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
/**
|
||||
* Lightning pulse information
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 3, 2014 3226 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public class LightningPulsePoint extends BaseLightningPoint {
|
||||
|
||||
private final LtgPulseType type;
|
||||
|
||||
public LightningPulsePoint(LtgPulseType type) {
|
||||
super();
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public LightningPulsePoint(Calendar time, LtgPulseType type) {
|
||||
super(time);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public LightningPulsePoint(double latitude, double longitude,
|
||||
Calendar time, LtgPulseType type) {
|
||||
super(latitude, longitude, time);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the type
|
||||
*/
|
||||
public LtgPulseType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
|
@ -19,53 +19,59 @@
|
|||
**/
|
||||
package com.raytheon.uf.common.dataplugin.binlightning.impl;
|
||||
|
||||
import com.raytheon.uf.edex.decodertools.core.BasePoint;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
|
||||
import com.raytheon.uf.common.time.util.TimeUtil;
|
||||
|
||||
/**
|
||||
* Record implementation for the Binary Lightning data decoder.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* 20070810 379 jkorman Initial Coding from prototype.
|
||||
* 20130227 DCS 152 jgerth Support for WWLLN and multiple sources
|
||||
* Jun 3, 2014 3226 bclement refactor to support pulse data
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @author jkorman
|
||||
* @version 1.0
|
||||
*/
|
||||
public class LightningStrikePoint extends BasePoint
|
||||
public class LightningStrikePoint extends BaseLightningPoint
|
||||
{
|
||||
|
||||
private LtgStrikeType type;
|
||||
|
||||
private LtgMsgType msgType;
|
||||
|
||||
// Lightning strike strength and polarity
|
||||
private double strikeStrength;
|
||||
|
||||
// Number of strikes for this record.
|
||||
private int strikeCount;
|
||||
// Number of pulses for this record.
|
||||
private int pulseCount;
|
||||
|
||||
// JJG - Lightning data source
|
||||
private String lightSource;
|
||||
|
||||
private List<LightningPulsePoint> pulses;
|
||||
|
||||
/**
|
||||
* Construct a LightningStrikePoint using given data.
|
||||
* @param base The base point which should contain a valid time.
|
||||
* @param latitude The latitude of the strike.
|
||||
* @param longitude The longitude of the strike.
|
||||
* @param type The strike message type.
|
||||
*
|
||||
* @param latitude
|
||||
* The latitude of the strike.
|
||||
* @param longitude
|
||||
* The longitude of the strike.
|
||||
* @param time
|
||||
* @param type
|
||||
* The strike message type.
|
||||
*/
|
||||
public LightningStrikePoint(BasePoint base, double latitude, double longitude, LtgMsgType type)
|
||||
public LightningStrikePoint(double latitude, double longitude,
|
||||
Calendar time, LtgMsgType type)
|
||||
{
|
||||
super(base);
|
||||
setLatitude(latitude);
|
||||
setLongitude(longitude);
|
||||
super(latitude, longitude, time);
|
||||
setElevation(0);
|
||||
this.msgType = type;
|
||||
}
|
||||
|
@ -77,44 +83,37 @@ public class LightningStrikePoint extends BasePoint
|
|||
*/
|
||||
public LightningStrikePoint(double latitude, double longitude)
|
||||
{
|
||||
super(latitude,longitude);
|
||||
super(latitude, longitude, TimeUtil.newGmtCalendar());
|
||||
setElevation(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the strike count.
|
||||
* @return The strike count.
|
||||
* @param time
|
||||
* @param type
|
||||
*/
|
||||
public int getStrikeCount()
|
||||
{
|
||||
return strikeCount;
|
||||
public LightningStrikePoint(Calendar time, LtgMsgType type) {
|
||||
super(time);
|
||||
this.msgType = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the strike count.
|
||||
* @return The strike count.
|
||||
* Get the pulse count.
|
||||
*
|
||||
* @return The pulse count.
|
||||
*/
|
||||
public void setStrikeCount(int strikeCount)
|
||||
public int getPulseCount()
|
||||
{
|
||||
this.strikeCount = strikeCount;
|
||||
return pulseCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the strike strength.
|
||||
* @return The strike strength.
|
||||
* Set the pulse count.
|
||||
*
|
||||
* @return The pulse count.
|
||||
*/
|
||||
public double getStrikeStrength()
|
||||
public void setPulseCount(int pulseCount)
|
||||
{
|
||||
return strikeStrength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the strike strength.
|
||||
* @return The strike strength.
|
||||
*/
|
||||
public void setStrikeStrength(double strikeStrength)
|
||||
{
|
||||
this.strikeStrength = strikeStrength;
|
||||
this.pulseCount = pulseCount;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -189,13 +188,22 @@ public class LightningStrikePoint extends BasePoint
|
|||
{
|
||||
buffer = new StringBuilder();
|
||||
}
|
||||
buffer.append(String.format("%4d%02d%02d",getYear(),getMonth(),getDay()));
|
||||
buffer.append(String.format("%02d%02d%02d",getHour(),getMinute(),getSecond()));
|
||||
Calendar obsTime = getTime();
|
||||
int year = obsTime.get(Calendar.YEAR);
|
||||
int month = obsTime.get(Calendar.MONTH) + 1;
|
||||
int day = obsTime.get(Calendar.DAY_OF_MONTH);
|
||||
int hour = obsTime.get(Calendar.HOUR);
|
||||
int minute = obsTime.get(Calendar.MINUTE);
|
||||
int second = obsTime.get(Calendar.SECOND);
|
||||
int millis = obsTime.get(Calendar.MILLISECOND);
|
||||
buffer.append(String.format("%4d%02d%02d", year, month, day));
|
||||
buffer.append(String.format("%02d%02d%02d", hour, minute, second));
|
||||
|
||||
buffer.append(String.format(" %9.5f %10.5f ",getLatitude(), getLongitude() ));
|
||||
buffer.append(String.format("%2s %2s ",msgType.getType(),type.getType()));
|
||||
|
||||
buffer.append(String.format("%4.0f %02d %02d", strikeStrength,(getMillis() / 100),strikeCount));
|
||||
buffer.append(String.format("%4.0f %02d %02d", getStrikeStrength(),
|
||||
(millis / 100), pulseCount));
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
@ -213,5 +221,20 @@ public class LightningStrikePoint extends BasePoint
|
|||
{
|
||||
return toString(null).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the pulses
|
||||
*/
|
||||
public List<LightningPulsePoint> getPulses() {
|
||||
return pulses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pulses
|
||||
* the pulses to set
|
||||
*/
|
||||
public void setPulses(List<LightningPulsePoint> pulses) {
|
||||
this.pulses = pulses;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,32 +23,51 @@ package com.raytheon.uf.common.dataplugin.binlightning.impl;
|
|||
* Enums for the lightning message type, Flash or RT Flash.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* 20070810 379 jkorman Initial Coding from prototype.
|
||||
* Jun 3, 2014 3226 bclement added id, added TOTAL_LIGHTNING
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @author jkorman
|
||||
* @version 1.0
|
||||
*/
|
||||
public enum LtgMsgType
|
||||
{
|
||||
STRIKE_MSG_FL("FL"),
|
||||
STRIKE_MSG_RT("RT");
|
||||
STRIKE_MSG_FL((byte) 0, "FL"), STRIKE_MSG_RT((byte) 1, "RT"), TOTAL_LIGHTNING(
|
||||
(byte) 2, "TL");
|
||||
|
||||
private final String strikeType;
|
||||
private final String msgType;
|
||||
|
||||
private final byte id;
|
||||
|
||||
/**
|
||||
* Construct the type.
|
||||
* @param type Lightning strike type.
|
||||
*
|
||||
* @param type
|
||||
* Lightning message type.
|
||||
*/
|
||||
private LtgMsgType(String type)
|
||||
private LtgMsgType(byte id, String type)
|
||||
{
|
||||
strikeType = type;
|
||||
this.msgType = type;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id
|
||||
* @return null if no type found for id
|
||||
*/
|
||||
public static LtgMsgType getById(byte id) {
|
||||
for (LtgMsgType type : LtgMsgType.values()) {
|
||||
if (type.id == id) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -57,6 +76,13 @@ public enum LtgMsgType
|
|||
*/
|
||||
public String getType()
|
||||
{
|
||||
return strikeType;
|
||||
return msgType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return unique id for type
|
||||
*/
|
||||
public byte getId() {
|
||||
return this.id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* 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 com.raytheon.uf.common.dataplugin.binlightning.impl;
|
||||
|
||||
/**
|
||||
* Stroke type enum for lightning pulses. Mainly categorizes between return and
|
||||
* non-return strokes.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jun 3, 2014 3226 bclement Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bclement
|
||||
* @version 1.0
|
||||
*/
|
||||
public enum LtgPulseType {
|
||||
|
||||
RETURN_STROKE((byte) 0), NON_RETURN_STROKE((byte) 1), KEEP_ALIVE((byte) 9);
|
||||
|
||||
private final byte id;
|
||||
|
||||
/**
|
||||
* @param id
|
||||
*/
|
||||
private LtgPulseType(byte id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id
|
||||
* @return null if no type is found for id
|
||||
*/
|
||||
public static LtgPulseType getById(byte id) {
|
||||
for (LtgPulseType type : LtgPulseType.values()) {
|
||||
if (type.id == id) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return unique id for this type
|
||||
*/
|
||||
public byte getId() {
|
||||
return this.id;
|
||||
}
|
||||
}
|
|
@ -23,34 +23,52 @@ package com.raytheon.uf.common.dataplugin.binlightning.impl;
|
|||
* Enums for the lightning strike type, cloud-to-cloud or cloud-to-ground.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* 20070810 379 jkorman Initial Coding from prototype.
|
||||
* 20130425 DCS 112 Wufeng Zhou Added STRIKE_TF (for Total Flash) in definition for Total Flash
|
||||
* Jun 3, 2014 3226 bclement added id, changed to more descriptive names, added KEEP_ALIVE
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @author jkorman
|
||||
* @version 1.0
|
||||
*/
|
||||
public enum LtgStrikeType
|
||||
{
|
||||
STRIKE_CC("CC"),
|
||||
STRIKE_CG("CG"),
|
||||
STRIKE_TF("TF");
|
||||
CLOUD_TO_CLOUD((byte)0, "CC"), CLOUD_TO_GROUND((byte)1, "CG"), TOTAL_FLASH((byte)2, "TF"), KEEP_ALIVE((byte)9,
|
||||
"");
|
||||
|
||||
private final String strikeType;
|
||||
|
||||
private final byte id;
|
||||
|
||||
/**
|
||||
* Construct the type.
|
||||
* @param id unique id for type
|
||||
* @param type Lightning strike type.
|
||||
*/
|
||||
private LtgStrikeType(String type)
|
||||
private LtgStrikeType(byte id, String type)
|
||||
{
|
||||
strikeType = type;
|
||||
this.id = id;
|
||||
this.strikeType = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id
|
||||
* unique id for type
|
||||
* @return null if no type is found for id
|
||||
*/
|
||||
public static LtgStrikeType getById(byte id) {
|
||||
for (LtgStrikeType type : LtgStrikeType.values()) {
|
||||
if (type.id == id) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -61,4 +79,11 @@ public enum LtgStrikeType
|
|||
{
|
||||
return strikeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return id
|
||||
*/
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,6 +76,8 @@ import com.vividsolutions.jts.io.WKTWriter;
|
|||
* 12/20/2013 DR 16894 gzhang Fixed getZRvalue2() bias issue.
|
||||
* 05/12/2014 3133 njensen Extracted getLightningRecord
|
||||
* 05/13/2014 3133 njensen Moved convertStrankValue here from ScanConfig
|
||||
* Jun 05, 2014 3226 bclement BinLightning refactor
|
||||
* compare lightning strike type by id instead of ordinal
|
||||
* </pre>
|
||||
*
|
||||
* @author dhladky
|
||||
|
@ -1292,7 +1294,7 @@ public class ScanUtils {
|
|||
(double) rec.getLatitudes()[i],
|
||||
(double) rec.getLongitudes()[i],
|
||||
rec.getIntensities()[i], rec.getStrikeTypes()[i],
|
||||
rec.getMsgTypes()[i], rec.getStrikeCounts()[i]);
|
||||
rec.getMsgTypes()[i], rec.getPulseCounts()[i]);
|
||||
|
||||
strikeList.add(strike);
|
||||
}
|
||||
|
@ -1311,7 +1313,7 @@ public class ScanUtils {
|
|||
if (ls.getIntensity() > 0) {
|
||||
totalPosStrikes++;
|
||||
}
|
||||
if (ls.getStrikeType() == LtgStrikeType.STRIKE_CG.ordinal()) {
|
||||
if (ls.getStrikeType() == LtgStrikeType.CLOUD_TO_GROUND.getId()) {
|
||||
totalCGStrikes++;
|
||||
}
|
||||
totalStrikes++;
|
||||
|
|
|
@ -19,12 +19,14 @@
|
|||
**/
|
||||
package com.raytheon.uf.edex.decodertools.core;
|
||||
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
|
||||
|
||||
/**
|
||||
* BasePoint provides a simple 4D (latitude, longitude, elevation, and time)
|
||||
* base class for observation data. Sub-classes of BasePoint are responsible for
|
||||
* adding additional checking or using specific units as required. An example
|
||||
* would be adding a accessors for a Calendar to expose the date information.
|
||||
* Most attributes of this class do not have units.
|
||||
* BasePoint provides a simple 3D (latitude, longitude, elevation) base class
|
||||
* for observation data. Sub-classes of BasePoint are responsible for adding
|
||||
* additional checking or using specific units as required. Most attributes of
|
||||
* this class do not have units.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
|
@ -35,11 +37,14 @@ package com.raytheon.uf.edex.decodertools.core;
|
|||
* 27 July 2007 411 jkorman Initial Development
|
||||
* 20070911 379 jkorman Added comments.
|
||||
* 20070912 379 jkorman Code review cleanup.
|
||||
* Jun 05, 2014 3226 bclement deprecated class, removed time
|
||||
* </pre>
|
||||
*
|
||||
* @deprecated use {@link Coordinate} instead
|
||||
* @author jkorman
|
||||
* @version 1
|
||||
*/
|
||||
@Deprecated
|
||||
public class BasePoint {
|
||||
private double latitude;
|
||||
|
||||
|
@ -47,20 +52,6 @@ public class BasePoint {
|
|||
|
||||
private double elevation;
|
||||
|
||||
private int year;
|
||||
|
||||
private int month;
|
||||
|
||||
private int day;
|
||||
|
||||
private int hour;
|
||||
|
||||
private int minute;
|
||||
|
||||
private int second;
|
||||
|
||||
private int millis;
|
||||
|
||||
/**
|
||||
* Create an empty basepoint instance.
|
||||
*/
|
||||
|
@ -74,16 +65,9 @@ public class BasePoint {
|
|||
* A basepoint to copy.
|
||||
*/
|
||||
public BasePoint(BasePoint point) {
|
||||
latitude = point.latitude;
|
||||
longitude = point.longitude;
|
||||
elevation = point.elevation;
|
||||
year = point.year;
|
||||
month = point.month;
|
||||
day = point.day;
|
||||
hour = point.hour;
|
||||
minute = point.minute;
|
||||
second = point.second;
|
||||
millis = point.millis;
|
||||
this.latitude = point.latitude;
|
||||
this.longitude = point.longitude;
|
||||
this.elevation = point.elevation;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -154,136 +138,4 @@ public class BasePoint {
|
|||
this.elevation = elevation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the year part of the date.
|
||||
*
|
||||
* @return The year.
|
||||
*/
|
||||
public int getYear() {
|
||||
return year;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the year part of the date.
|
||||
*
|
||||
* @param year
|
||||
* Year.
|
||||
*/
|
||||
public void setYear(int year) {
|
||||
this.year = year;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the month part of the date.
|
||||
*
|
||||
* @return The month of the year.
|
||||
*/
|
||||
public int getMonth() {
|
||||
return month;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the day of the month part of the date.
|
||||
*
|
||||
* @param day
|
||||
* Day of month [1..12].
|
||||
*/
|
||||
public void setMonth(int month) {
|
||||
this.month = month;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the day part of the month.
|
||||
*
|
||||
* @return The day of the month.
|
||||
*/
|
||||
public int getDay() {
|
||||
return day;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the day of the month part of the date.
|
||||
*
|
||||
* @param day
|
||||
* Day of month [1..12].
|
||||
*/
|
||||
public void setDay(int day) {
|
||||
this.day = day;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hours part of the day.
|
||||
*
|
||||
* @return The hours part of the day.
|
||||
*/
|
||||
public int getHour() {
|
||||
return hour;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the hour part of the time.
|
||||
*
|
||||
* @param hour
|
||||
* Hour of the day [0..23].
|
||||
*/
|
||||
public void setHour(int hour) {
|
||||
this.hour = hour;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the minutes part of the hour.
|
||||
*
|
||||
* @return The minutes part of the hour.
|
||||
*/
|
||||
public int getMinute() {
|
||||
return minute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the minute of the hour.
|
||||
*
|
||||
* @param minute
|
||||
* The minute of the hour [0..59]
|
||||
*/
|
||||
public void setMinute(int minute) {
|
||||
this.minute = minute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the seconds part of the minute.
|
||||
*
|
||||
* @return The seconds part of the minute.
|
||||
*/
|
||||
public int getSecond() {
|
||||
return second;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the second of the minute.
|
||||
*
|
||||
* @param second
|
||||
* The second of the minute [0..59]
|
||||
*/
|
||||
public void setSecond(int second) {
|
||||
this.second = second;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the milliseconds part of the time.
|
||||
*
|
||||
* @return The milliseconds part of the time.
|
||||
*/
|
||||
public int getMillis() {
|
||||
return millis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the milliseconds part of the time.
|
||||
*
|
||||
* @param millis
|
||||
* Milliseconds [0..999].
|
||||
*/
|
||||
public void setMillis(int millis) {
|
||||
this.millis = millis;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ import com.vividsolutions.jts.geom.Coordinate;
|
|||
* Jan 10, 2013 1448 bgonzale Added app context check in runOnSchedule().
|
||||
* Jan 18, 2013 1469 bkowal Removed the hdf5 data directory.
|
||||
* Mar 28, 2014 2952 mpduff Changed to use UFStatus for logging.
|
||||
* Jun 05, 2014 3226 bclement BinLightning refactor
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -138,7 +139,7 @@ public class MpeLightningSrv {
|
|||
float[] latitudes = ltngRec.getLatitudes();
|
||||
float[] longitudes = ltngRec.getLongitudes();
|
||||
long[] obstimes = ltngRec.getObsTimes();
|
||||
byte[] strikes = ltngRec.getStrikeCounts();
|
||||
byte[] strikes = ltngRec.getPulseCounts();
|
||||
|
||||
// convert latitude and longitude to grid coordinate
|
||||
HRAP hrap = HRAP.getInstance();
|
||||
|
|
|
@ -58,6 +58,7 @@ import com.vividsolutions.jts.geom.GeometryFactory;
|
|||
* ------------ ---------- ----------- --------------------------
|
||||
* 05/07/2009 2037 dhladky Initial Creation.
|
||||
* Apr 30, 2014 2060 njensen Updates for removal of grid dataURI column
|
||||
* Jun 05, 2014 3226 bclement compare lightning strike type by id instead of ordinal
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -292,7 +293,7 @@ public abstract class ScanProduct implements Serializable {
|
|||
rec.getIntensities()[i],
|
||||
rec.getStrikeTypes()[i],
|
||||
rec.getMsgTypes()[i],
|
||||
rec.getStrikeCounts()[i]);
|
||||
rec.getPulseCounts()[i]);
|
||||
|
||||
strikeList.add(strike);
|
||||
}
|
||||
|
@ -310,8 +311,8 @@ public abstract class ScanProduct implements Serializable {
|
|||
if (ls.getIntensity() > 0) {
|
||||
totalPosStrikes++;
|
||||
}
|
||||
if (ls.getStrikeType() == LtgStrikeType.STRIKE_CG
|
||||
.ordinal()) {
|
||||
if (ls.getStrikeType() == LtgStrikeType.CLOUD_TO_GROUND
|
||||
.getId()) {
|
||||
totalCGStrikes++;
|
||||
}
|
||||
totalStrikes++;
|
||||
|
|
|
@ -3,8 +3,8 @@ package gov.noaa.nws.ncep.viz.rsc.lightning.rsc;
|
|||
import gov.noaa.nws.ncep.viz.common.ui.NmapCommon;
|
||||
import gov.noaa.nws.ncep.viz.resources.AbstractNatlCntrsResource;
|
||||
import gov.noaa.nws.ncep.viz.resources.INatlCntrsResource;
|
||||
import gov.noaa.nws.ncep.viz.resources.colorBar.ColorBarResourceData;
|
||||
import gov.noaa.nws.ncep.viz.resources.colorBar.ColorBarResource;
|
||||
import gov.noaa.nws.ncep.viz.resources.colorBar.ColorBarResourceData;
|
||||
import gov.noaa.nws.ncep.viz.ui.display.ColorBar;
|
||||
import gov.noaa.nws.ncep.viz.ui.display.NCMapDescriptor;
|
||||
|
||||
|
@ -18,6 +18,7 @@ import java.util.List;
|
|||
import com.raytheon.uf.common.dataplugin.HDF5Util;
|
||||
import com.raytheon.uf.common.dataplugin.PluginDataObject;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.BinLightningRecord;
|
||||
import com.raytheon.uf.common.dataplugin.binlightning.LightningConstants;
|
||||
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
|
||||
import com.raytheon.uf.common.datastorage.DataStoreFactory;
|
||||
import com.raytheon.uf.common.datastorage.IDataStore;
|
||||
|
@ -42,15 +43,14 @@ import com.raytheon.uf.viz.core.drawables.IWireframeShape;
|
|||
import com.raytheon.uf.viz.core.drawables.PaintProperties;
|
||||
import com.raytheon.uf.viz.core.drawables.ResourcePair;
|
||||
import com.raytheon.uf.viz.core.exception.VizException;
|
||||
import com.raytheon.uf.viz.core.map.MapDescriptor;
|
||||
import com.raytheon.uf.viz.core.rsc.LoadProperties;
|
||||
import com.raytheon.uf.viz.core.rsc.ResourceProperties;
|
||||
import com.raytheon.uf.viz.core.rsc.ResourceType;
|
||||
|
||||
|
||||
/**
|
||||
* LigntningResource - Display Lightning data.
|
||||
* *
|
||||
* LigntningResource - Display Lightning data. *
|
||||
*
|
||||
* <pre>
|
||||
* SOFTWARE HISTORY
|
||||
* Date Ticket# Engineer Description
|
||||
|
@ -65,10 +65,11 @@ import com.raytheon.uf.viz.core.rsc.ResourceType;
|
|||
* 05/23/12 785 Q. Zhou Added getName for legend.
|
||||
* 12/19/2012 #960 Greg Hull override propertiesChanged() to update colorBar.
|
||||
* 05/07/2013 #993 Greg Hull change key for strikeMap from URI to the HDF5 group
|
||||
*
|
||||
* Jun 05, 2014 3226 bclement reference datarecords by LightningConstants
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author ghull
|
||||
* @author ghull
|
||||
* @version 1.0
|
||||
*/
|
||||
public class LightningResource extends AbstractNatlCntrsResource<LightningResourceData, NCMapDescriptor>
|
||||
|
@ -366,20 +367,17 @@ public class LightningResource extends AbstractNatlCntrsResource<LightningResour
|
|||
|
||||
for( int s=0 ; s<hdf5Rec.getSizes()[0] ; s++ ) {
|
||||
LtngStrikeDataObj strikeInfo = strikeList.get(s);
|
||||
if( hdf5Rec.getName().equals("intensity") ) {
|
||||
String name = hdf5Rec.getName();
|
||||
if (name.equals(LightningConstants.INTENSITY_DATASET)) {
|
||||
strikeInfo.intensity = ((IntegerDataRecord) hdf5Rec).getIntData()[s];
|
||||
} else if( hdf5Rec.getName().equals("latitude") ) {
|
||||
} else if (name.equals(LightningConstants.LAT_DATASET)) {
|
||||
strikeInfo.lat = ((FloatDataRecord) hdf5Rec).getFloatData()[s];
|
||||
} else if( hdf5Rec.getName().equals("longitude") ) {
|
||||
} else if (name.equals(LightningConstants.LON_DATASET)) {
|
||||
strikeInfo.lon = ((FloatDataRecord) hdf5Rec).getFloatData()[s];
|
||||
} else if( hdf5Rec.getName().equals("obsTime") ) {
|
||||
} else if (name.equals(LightningConstants.TIME_DATASET)) {
|
||||
strikeInfo.strikeTime = ((LongDataRecord) hdf5Rec).getLongData()[s];
|
||||
// if( strikeInfo.obsTime > latestStrike ) {
|
||||
// latestStrike = strikeInfo.obsTime;
|
||||
// }
|
||||
// } else if( hdf5Rec.getName().equals("strikeCount") ) {
|
||||
// strikeInfo.lon = ((FloatDataRecord) hdf5Rec).getFloatData()[s];
|
||||
} else if( hdf5Rec.getName().equals("msgType") ) {
|
||||
} else if (name
|
||||
.equals(LightningConstants.MSG_TYPE_DATASET)) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgMsgType;
|
|||
import com.raytheon.uf.common.dataplugin.binlightning.impl.LtgStrikeType;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
import com.raytheon.uf.edex.decodertools.core.BasePoint;
|
||||
|
||||
/**
|
||||
* BinLigntningDecoderUtil
|
||||
|
@ -38,6 +37,7 @@ import com.raytheon.uf.edex.decodertools.core.BasePoint;
|
|||
* moved from com.raytheon.edex.plugin.binlightning to gov.noaa.nws.ost.edex.plugin.binlightning
|
||||
* moved decodeBinLightningData() and decodeBitShiftedBinLightningData()
|
||||
* to BinLightningDecoder to solve circular dependency
|
||||
* Jun 05, 2014 3226 bclement LightningStrikePoint refactor
|
||||
* </pre>
|
||||
*
|
||||
* @author Wufeng Zhou
|
||||
|
@ -132,20 +132,16 @@ public class BinLightningDecoderUtil {
|
|||
// int reserved = buffer.getShort() & 0xffff;
|
||||
|
||||
// Create the strike record from the report info and base time information.
|
||||
BasePoint base = new BasePoint(lat, lon);
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTimeInMillis(epochTime);
|
||||
base.setYear(cal.get(Calendar.YEAR));
|
||||
base.setMonth(cal.get(Calendar.MONTH) + 1);
|
||||
base.setDay(cal.get(Calendar.DAY_OF_MONTH));
|
||||
base.setHour(cal.get(Calendar.HOUR_OF_DAY));
|
||||
base.setMinute(cal.get(Calendar.MINUTE));
|
||||
base.setSecond(cal.get(Calendar.SECOND));
|
||||
base.setMillis(cal.get(Calendar.MILLISECOND));
|
||||
|
||||
// new spec does not seem to have lightning message type indicator such as FL (Flash Lightning) or RT (Real Time flash lightning)
|
||||
// The source of lightning data in the vendor specific data bytes (byte 16-17) may related to this (???),
|
||||
// and it is used here for now. 04/182/013 Wufeng Zhou
|
||||
/*
|
||||
* new spec does not seem to have lightning message type indicator
|
||||
* such as FL (Flash Lightning) or RT (Real Time flash lightning)
|
||||
* The source of lightning data in the vendor specific data bytes
|
||||
* (byte 16-17) may related to this (???),
|
||||
* and it is used here for now. 04/182/013 Wufeng Zhou
|
||||
*/
|
||||
/** 05/02/2013, found DSI-9603 Spec (http://www1.ncdc.noaa.gov/pub/data/documentlibrary/tddoc/td9603.pdf) on NLDN lightning data format,
|
||||
* on Message Type and Stroke Type:
|
||||
* POS: 37-38 Message Type
|
||||
|
@ -165,19 +161,24 @@ public class BinLightningDecoderUtil {
|
|||
msgType = LtgMsgType.STRIKE_MSG_RT;
|
||||
}
|
||||
|
||||
LightningStrikePoint lsp = new LightningStrikePoint(base, lat, lon, msgType);
|
||||
LtgStrikeType ltgStrikeType = LtgStrikeType.STRIKE_CG; // default ??
|
||||
LightningStrikePoint lsp = new LightningStrikePoint(lat, lon, cal,
|
||||
msgType);
|
||||
LtgStrikeType ltgStrikeType = LtgStrikeType.CLOUD_TO_GROUND; // default ??
|
||||
if (strokeType == 0x0000) {
|
||||
ltgStrikeType = LtgStrikeType.STRIKE_CG;
|
||||
ltgStrikeType = LtgStrikeType.CLOUD_TO_GROUND;
|
||||
} else if (strokeType == 0x00ff) {
|
||||
ltgStrikeType = LtgStrikeType.STRIKE_CC;
|
||||
ltgStrikeType = LtgStrikeType.CLOUD_TO_CLOUD;
|
||||
} else if (strokeType == 0xffff) {
|
||||
ltgStrikeType = LtgStrikeType.STRIKE_TF;
|
||||
ltgStrikeType = LtgStrikeType.TOTAL_FLASH;
|
||||
}
|
||||
lsp.setType(ltgStrikeType);
|
||||
|
||||
// as of OB13.3 for World Wide Lightning Location Network (WWLLN) data (decoded by textlightning though, not this bin lightning decoder),
|
||||
// added lightning source field in LightningStrikePoint, as well as column in binlightning database table defaults to NLDN
|
||||
/*
|
||||
* as of OB13.3 for World Wide Lightning Location Network (WWLLN)
|
||||
* data (decoded by textlightning though, not this bin lightning
|
||||
* decoder), added lightning source field in LightningStrikePoint,
|
||||
* as well as column in binlightning database table defaults to NLDN
|
||||
*/
|
||||
if (vendor == ((short)0x0001)) { // CONUS source
|
||||
lsp.setLightSource("NLDN");
|
||||
} else if (vendor == ((short)0x0002)) { // long range source, i.e., GLD360.
|
||||
|
@ -185,7 +186,7 @@ public class BinLightningDecoderUtil {
|
|||
lsp.setLightSource("GLD");
|
||||
}
|
||||
|
||||
lsp.setStrikeCount(strokeMultiplicity);
|
||||
lsp.setPulseCount(strokeMultiplicity);
|
||||
lsp.setStrikeStrength(strokeKiloAmps);
|
||||
// stroke duration does not seem to be used
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue