Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
No Format
package nl.wldelft.timeseriesparsers;

import nl.wldelft.util.DateUtils;
import nl.wldelft.util.IOUtils;
import nl.wldelft.util.io.BinaryParser;
import nl.wldelft.util.io.LittleEndianDataInputStream;
import nl.wldelft.util.timeseries.DefaultTimeSeriesHeader;
import nl.wldelft.util.timeseries.TimeSeriesContentHandler;
import org.apache.log4j.Logger;

import java.io.BufferedInputStream;
import java.io.EOFException;
import java.io.IOException;

/**
 * TimeSeries reader for Keller AG *.IDC files
 *
 */
public class IdcTimeSeriesParser implements BinaryParser<TimeSeriesContentHandler> {

    private static final Logger log = Logger.getLogger(IdcTimeSeriesParser.class);

    // Constanten
    private static final int DF_ID_FILE = 0;
    private static final int DF_ID_DEVICE = 1;
    private static final int DF_ID_DATA = 2;
    private static final int DF_ID_UNITS = 3;
    private static final int DF_ID_PROFILE = 4;
    private static final int DF_ID_CONFIG = 5;
    private static final int DF_ID_WL_CONVERTED = 6;
    private static final int DF_ID_AIR_COMPENSATED = 7;
    private static final int DF_ID_INFO = 8;

    //
    private LittleEndianDataInputStream is = null;
    private TimeSeriesContentHandler contentHandler = null;
    private Stringint locationIdrawTimeZoneOffset;

    /**
     * Parse Keller AG *.idc bestand
     *
     * @param inputStream
     * @param virtualFileName
     * @param contentHandler
     * @throws Exception
     */
    @Override
    public void parse(BufferedInputStream inputStream, String virtualFileName, TimeSeriesContentHandler contentHandler) throws Exception {

        intthis.is rawTimeZoneOffset= =new contentHandler.getDefaultTimeZoneLittleEndianDataInputStream(inputStream).getRawOffset();
        this.iscontentHandler = new LittleEndianDataInputStream(inputStream);
contentHandler;
        booleanthis.rawTimeZoneOffset abVersion0310 = falsecontentHandler.getDefaultTimeZone().getRawOffset();

        shortboolean amountOfUnitsabVersion0310 = 0false;
        shortString availableChannelslocationId = 0"";

        float[] userValArr = new float[12];

        DefaultTimeSeriesHeaderfloat headerinstallationDepth = new DefaultTimeSeriesHeader()0f;

        //float ContinueheightOfWellhead to= read0f;
 lines while
      float offset // there are still some left to read
        while (true) {
    = 0f;
        float waterDensity = 0f;
        byte batteryCapacity = 0;

        //long ReadstartTime block ID= Long.MIN_VALUE;

        DefaultTimeSeriesHeader header =  short blockIdnew DefaultTimeSeriesHeader();

        DefaultTimeSeriesHeader headerEq =  try {new DefaultTimeSeriesHeader();

        // Continue to read lines while
   blockId = readBlock();
   // there are still some left to read
  } catch (EOFException e) {
  while (true) {
            returnis.mark(1);
            }
int nextByte           switch (blockId) {= is.read();
            if (nextByte ==  case DF_ID_FILE:

-1) break; // EOF
            is.reset();
        // File Identification
  // Read block ID
            short  blockId String version = readStringreadBlock();

            switch (blockId) {
      //log.debug(version);
          case DF_ID_FILE:
         break;

           // File Identification
   case DF_ID_DEVICE:

                String version   // Device properties= readString();
                    int lw = this.is.readInt();
     if (log.isDebugEnabled()) log.debug("version = " + version);
               int w1 = lw / 65536break;

                    int w2 = lw % 65536;case DF_ID_DEVICE:

                    int// klasse = w1 / 256;Device properties
                    int groeplw = w1 % 256this.is.readInt();
                    int jaarw1 = w2lw / 25665536;
                    int weekw2 = w2lw % 25665536;

                    ifint (jaarklasse == w1 3)/ {256;
                    int groep = w1 if (week >= 10) {% 256;
                    int jaar = w2     abVersion0310 = true/ 256;
                    int week = w2 }% 256;

                    }
if (jaar == 3) {
                        if (jaarweek >= 310) {
                            abVersion0310 = true;
                     }

   }
                 int serialNumber = this.is.readInt(); }
                    booleanif configuredAsWaterlevel(jaar = this.is.readBoolean();
> 3) {
                      locationId  abVersion0310 = readString()true;
                    log.debug(locationId);}

                    Stringint commentserialNumber = readStringthis.is.readInt();

                    log.debug(commentboolean configuredAsWaterlevel = this.is.readBoolean();

                    locationId break= readString();

                    String comment case DF_ID_DATA:= readString();

                    // Data recordsif (log.isDebugEnabled()) {
                    int  z = thislog.is.readInt(debug("serial number = " + serialNumber);
                    if (z > 0) {

      log.debug("configured as waterlevel = " + configuredAsWaterlevel);
                   for (int i = 0; i < z; i++) { log.debug("comment = " + comment);
                        log.debug("location id = " // datum+ locationId);
    8 bytes double
              }

              //   channel  1 bytebreak;

                case DF_ID_DATA:

           //         // 3Data bytes skiprecords
                    int z = this.is.readInt();
     // value    4 bytes float
        for (int i = 0; i < z; i++) {
           // lw       4 bytes int
   // datum    8 bytes double
                  //      // channel  1 4byte
 bytes skip

                      //      double doubleTime = is.readDouble();
 3 bytes skip
                         long time = DateUtils.toTimeFromMicrosoftComDate(doubleTime);// value    4 bytes float
                        // lw   contentHandler.setTime(time);
    4 bytes int
                      byte channel = this.is.readByte();
//          4 bytes skip
                 contentHandler.setTimeSeriesHeader(channel);
       // The date is stored as the number of days since 30 Dec 1899. Quite why it is not 31 Dec IOUtils.skipFully(is, 3);
    is not clear. 01 Jan 1900 has a days value of 2.
                        floatdouble singleValuedoubleTime = this.is.readFloatreadDouble();

                        long time =  contentHandlerDateUtils.setValuetoTimeFromMicrosoftComDate(singleValuedoubleTime);

                        // Bewaar lijst  contentHandler.applyCurrentFields();
     met tijden voor de reeks met inhangdiepte's
                       int if longValue(startTime == this.is.readInt();
   Long.MIN_VALUE) startTime = time;

                         IOUtilscontentHandler.skipFullysetTime(is, 4new Long(time));

                        byte channel  }= this.is.readByte();

                    }
    contentHandler.setTimeSeriesHeader(channel);

                break;

        IOUtils.skipFully(is, 3);
       case DF_ID_UNITS:

                float singleValue =  // Units
this.is.readFloat();
                      availableChannels = thiscontentHandler.is.readShortsetValue(singleValue);
                    amountOfUnits   = thiscontentHandler.is.readShortapplyCurrentFields();
                        int longValue = logthis.is.debug("availableChannels" + availableChannelsreadInt();
                    log.debug("amountOfUnits" + amountOfUnits);

       // Skip 4 bytes
                 for (int i = 0; i < amountOfUnits; i++) { IOUtils.skipFully(is, 4);
                    }
    byte channel = this.is.readByte();
              break;

             byte[] text = new byte[7];case DF_ID_UNITS:

                    boolean retval   this.is.read(text, 0, 7= parseUnits(locationId, header);
                    if (!retval){
   float multiplier = this.is.readFloat();
                  log.error("Bestand bevat niet de juiste eenheden");
 float offset = this.is.readFloat();
                    throw new Exception("Bestand bevat byte[]niet descriptionde = new byte[41]juiste eenheden");
                    }
    this.is.read(description, 0, 41);
              break;

          IOUtils.skipFully(is, 3);

     case DF_ID_PROFILE:

                  if ((channel == 0) || (channel == 1) || (channel == 2)) { // Read device profile
                    for (int i = 0; i <  header.setUnit("bar");userValArr.length; i++) {
                        } else {
  userValArr[i] = this.is.readFloat();
                          if ((channel == 3) || (channel == 4) || (channel == 5)) {
log.isDebugEnabled()) log.debug("userValArr " + userValArr[i]);
                    }

                    installationDepth  header.setUnit("°C")= userValArr[2];
                    if (log.isDebugEnabled()) log.debug("installation depth " + installationDepth);


  }   else {
              heightOfWellhead = userValArr[3];
                header.setUnit("");
          if (log.isDebugEnabled()) log.debug("Height of wellhead above sea level " + heightOfWellhead);

                    offset = }userValArr[4];
                    if (log.isDebugEnabled()) log.debug("Offset " + }offset);

                    waterDensity    header.setLocationId(locationId)= userValArr[5];
                        header.setParameterId(Byte.toString(channel))if (log.isDebugEnabled()) log.debug("Water density " + waterDensity);


                    short availableChannels =  contentHandler.createTimeSeriesHeaderAlias(channel, headerthis.is.readShort();

                    }
if ((availableChannels & 2) == 2) {
              break;

          float p1min     case DF_ID_PROFILE:

= this.is.readFloat();
                    // Read device profile
 float p1max = this.is.readFloat();
                   for (int i = 0; i < userValArr.length; i++) {if (log.isDebugEnabled()) log.debug("P1 min " + p1min);
                        userValArr[i] = this.is.readFloat(if (log.isDebugEnabled()) log.debug("P1 max " + p1max);
                    }
                    if ((availableChannels & 4) = this.is.readShort();

= 4) {
                      if ((availableChannels &float 2)p2min == 2) {this.is.readFloat();
                        float p1minp2max = this.is.readFloat();
                        float p1max = this.is.readFloat(if (log.isDebugEnabled()) log.debug("P2 min " + p2min);
                    }
    if (log.isDebugEnabled()) log.debug("P2 max " + p2max);
           if          }
                    if ((availableChannels & 48) == 48) {
                        float p2mint1min = this.is.readFloat();
                        float p2maxt1max = this.is.readFloat();
                    }
                    if ((availableChannels & 8) == 8) {log.isDebugEnabled()) log.debug("T1 min " + t1min);
                        float t1min = this.is.readFloat();
                        float t1max = this.is.readFloat(if (log.isDebugEnabled()) log.debug("T1 max " + t1max);
                    }
                    if ((availableChannels & 16) == 16) {
                        float tob1min = this.is.readFloat();
                        float tob1max = this.is.readFloat();
                    }
    if (log.isDebugEnabled()) log.debug("TOB1 min " + tob1min);
          if  ((availableChannels & 32) == 32) {
       if (log.isDebugEnabled()) log.debug("TOB1 max " + tob1max);
           float tob2min = this.is.readFloat();
      }
                  float tob2max = this.is.readFloat();
   if ((availableChannels & 32) == 32) {
                 }
       float tob2min = this.is.readFloat();
          break;

              float tob2max case DF_ID_CONFIG:

= this.is.readFloat();
                        if (log.isDebugEnabled()) log.debug("TOB2 min //" Record+ configurationtob2min);
                    int   startDate =if this.is.readInt((log.isDebugEnabled()) log.debug("TOB2 max " + tob2max);
                    int stopDate = this.is.readInt();}

                    lw = this.is.readInt()break;

                case DF_ID_CONFIG:

               int  recordedChannels = lw // 65536;Record configuration
                    int recordModusstartDate = lw % 65536this.is.readInt();

                    floatint trigger1stopDate = this.is.readFloatreadInt();
                    floatlw trigger2 = this.is.readFloatreadInt();

                    ifint (abVersion0310) {
   recordedChannels = lw / 65536;
                     int recFixCounterrecordModus = lw % 65536;

                    float trigger1 = this.is.readIntreadFloat();
                    float trigger2   short recModCounter = this.is.readShortreadFloat();

                    }if else(abVersion0310) {
                        lwint recFixCounter = this.is.readInt();
                        intshort recFixCounterrecModCounter = lw / 65536this.is.readShort();
                    } else {
  int tmp = lw % 65536;
                 lw       short recModCounter = (short) tmp= this.is.readInt();
                    }

    int recFixCounter = lw / 65536;
           short sw = this.is.readShort();

                    int tmp = swlw /% 25665536;
                        short recModChannelrecModCounter = (short) tmp;
                    tmp = sw % 256;}

                    short recSaveCountersw = this.is.readShort(short) tmp;

                    shortint recFastModCountertmp = this.is.readShort() sw / 256;
                    booleanshort recEndlessrecModChannel = this.is.readBoolean(short) tmp;
                    tmp = sw % break256;

                    short recSaveCounter = case DF_ID_WL_CONVERTED:(short) tmp;

                    // Waterlevel convertedshort recFastModCounter = this.is.readShort();
                    boolean convertedIntoWaterlevelrecEndless = this.is.readBoolean();
                    break;

                case DF_ID_AIRWL_COMPENSATEDCONVERTED:

                    // AirpressureWaterlevel compensationconverted
                    boolean airCompensatedconvertedIntoWaterlevel = is.readBoolean();
                    break;

                case DF_ID_INFOAIR_COMPENSATED:

                    // AdditionalAirpressure informationcompensation
                    byteboolean batteryCapacityairCompensated = this.is.readBytereadBoolean();
                    for (int i = 0; i < 10; i++) {
break;

                case DF_ID_INFO:

                int reserve = this.is.readInt();
    // Additional information
                 }
   batteryCapacity = this.is.readByte();
               // Read CRC16 sum of the whole file for (int i = 0; i < 10; i++) {
                    short crc16    int reserve = this.is.readShortreadInt();
                    break;}
            }
        }

// Read CRC16 sum }


of the whole  /**file
     * Read block identification
     * @return block identification
    short *crc16 @throws IOException
     */
    private short readBlock() throws IOException {
= is.readShort();
                    break;
            }
        }

        // Inhangdiepte
        headerEq.setLocationId(locationId);
        contentHandler.setTime(startTime);

        headerEq.setParameterId("InstallationDepth");
        headerEq.setUnit("m");
        contentHandler.setTimeSeriesHeader(headerEq);
        contentHandler.setValue(installationDepth);
        contentHandler.applyCurrentFields();

        headerEq.setParameterId("HeightOfWellhead");
        headerEq.setUnit("m");
        contentHandler.setTimeSeriesHeader(headerEq);
        contentHandler.setValue(heightOfWellhead);
        contentHandler.applyCurrentFields();

        headerEq.setParameterId("Offset");
        headerEq.setUnit("m");
        contentHandler.setTimeSeriesHeader(headerEq);
        contentHandler.setValue(offset);
        contentHandler.applyCurrentFields();

        headerEq.setParameterId("WaterDensity");
        headerEq.setUnit("kg/m3");
        contentHandler.setTimeSeriesHeader(headerEq);
        contentHandler.setValue(waterDensity);
        contentHandler.applyCurrentFields();

        headerEq.setParameterId("BatteryCapacity");
        headerEq.setUnit("%");
        contentHandler.setTimeSeriesHeader(headerEq);
        contentHandler.setValue(batteryCapacity);
        contentHandler.applyCurrentFields();
    }

    /**
     * Read block identification
     * @return block identification
     * @throws IOException
     */
    private short readBlock() throws IOException {
        short block = this.is.readShort();
        short w1 = this.is.readShort();
        short w2 = this.is.readShort();

        int n = (65536 * w1) + w2;
        return block;
    }

    /**
     *
     *
     *
     * @param locationId
     * @param header
     * @return
     * @throws java.io.IOException
     */
    private boolean parseUnits(
            String locationId,
            DefaultTimeSeriesHeader header) throws IOException {

        boolean retval = true;
        short availableChannels = this.is.readShort();
        short amountOfUnits = this.is.readShort();

        for (int i = 0; i < amountOfUnits; i++) {

            // Kanaal
            byte channel = this.is.readByte();

            // Eenheid
            byte[] bytes = new byte[7];
            this.is.read(bytes, 0, 7);
            String unit = new String(bytes, 1, bytes[0]);
            if(unit.equalsIgnoreCase("m")){
               retval = false;
            }


            header.setUnit(unit);
            if (unit.contains("°C")) {
                header.setUnit("deg C");
            }

            // Multiplier
            float multiplier = this.is.readFloat();
            // Offet
            float offset = this.is.readFloat();

            // Description
            bytes = new byte[41];
            this.is.read(bytes, 0, 41);
            String description = new String(bytes, 1, bytes[0]);
            IOUtils.skipFully(is, 3);

            if (log.isDebugEnabled()) {
                log.debug("channel " + channel);
                log.debug("multiplier " + multiplier);
             short block = thislog.is.readShort(debug("offset " + offset);
             short w1 = thislog.is.readShort(debug("unit " + unit);
        short w2 = this.is.readShort(        log.debug("description " + description);

         int n = (65536}

 * w1) + w2;
        logheader.debug("BlocksetLocationId(locationId);
          : " + Short header.setParameterId(Byte.toString(blockchannel));

            logcontentHandler.debug("Buffer lengte  : " + Integer.toString(n));createTimeSeriesHeaderAlias(channel, header);
        }

        return blockretval;
    }

    /**
     * Read a string from file
     * @return string from file
     * @throws Exception
     */
    private String readString() throws IOException {
        String retval = "";
        // lees lengte van de string
        short length = this.is.readShort();
        if (length > 0) {
            // 	Create the byte array to hold the data
            byte[] bytes = new byte[length];

            int nob = this.is.read(bytes, 0, length);
            if (nob == length) {
                retval = new String(bytes);
            }

        }
        return retval;
    }
}