You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Next »

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 String locationId;

    /**
     * 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 {
        int rawTimeZoneOffset = contentHandler.getDefaultTimeZone().getRawOffset();
        this.is = new LittleEndianDataInputStream(inputStream);

        boolean abVersion0310 = false;
        short amountOfUnits = 0;
        short availableChannels = 0;

        float[] userValArr = new float[12];

        DefaultTimeSeriesHeader header = new DefaultTimeSeriesHeader();

        // Continue to read lines while
        // there are still some left to read
        while (true) {
            // Read block ID
            short blockId;
            try {
                blockId = readBlock();
            } catch (EOFException e) {
                return;
            }
            switch (blockId) {
                case DF_ID_FILE:

                    // File Identification
                    String version = readString();
                    //log.debug(version);
                    break;

                case DF_ID_DEVICE:

                    // Device properties
                    int lw = this.is.readInt();
                    int w1 = lw / 65536;
                    int w2 = lw % 65536;

                    int klasse = w1 / 256;
                    int groep = w1 % 256;
                    int jaar = w2 / 256;
                    int week = w2 % 256;

                    if (jaar == 3) {
                        if (week >= 10) {
                            abVersion0310 = true;
                        }
                    }
                    if (jaar > 3) {
                        abVersion0310 = true;
                    }

                    int serialNumber = this.is.readInt();
                    boolean configuredAsWaterlevel = this.is.readBoolean();
                    locationId = readString();
                    log.debug(locationId);
                    String comment = readString();
                    log.debug(comment);
                    break;

                case DF_ID_DATA:

                    // Data records
                    int z = this.is.readInt();
                    if (z > 0) {

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

                            double doubleTime = is.readDouble();
                            long time = DateUtils.toTimeFromMicrosoftComDate(doubleTime);
                            contentHandler.setTime(time);
                            byte channel = this.is.readByte();
                            contentHandler.setTimeSeriesHeader(channel);
                            IOUtils.skipFully(is, 3);
                            float singleValue = this.is.readFloat();
                            contentHandler.setValue(singleValue);
                            contentHandler.applyCurrentFields();
                            int longValue = this.is.readInt();
                            IOUtils.skipFully(is, 4);

                        }
                    }
                    break;

                case DF_ID_UNITS:

                    // Units
                    availableChannels = this.is.readShort();
                    amountOfUnits = this.is.readShort();
                    log.debug("availableChannels" + availableChannels);
                    log.debug("amountOfUnits" + amountOfUnits);

                    for (int i = 0; i < amountOfUnits; i++) {
                        byte channel = this.is.readByte();
                        byte[] text = new byte[7];
                        this.is.read(text, 0, 7);
                        float multiplier = this.is.readFloat();
                        float offset = this.is.readFloat();
                        byte[] description = new byte[41];
                        this.is.read(description, 0, 41);
                        IOUtils.skipFully(is, 3);

                        if ((channel == 0) || (channel == 1) || (channel == 2)) {
                            header.setUnit("bar");
                        } else {
                            if ((channel == 3) || (channel == 4) || (channel == 5)) {
                                header.setUnit("°C");
                            } else {
                                header.setUnit("");
                            }
                        }

                        header.setLocationId(locationId);
                        header.setParameterId(Byte.toString(channel));

                        contentHandler.createTimeSeriesHeaderAlias(channel, header);

                    }
                    break;

                case DF_ID_PROFILE:

                    // Read device profile
                    for (int i = 0; i < userValArr.length; i++) {
                        userValArr[i] = this.is.readFloat();
                    }
                    availableChannels = this.is.readShort();

                    if ((availableChannels & 2) == 2) {
                        float p1min = this.is.readFloat();
                        float p1max = this.is.readFloat();
                    }
                    if ((availableChannels & 4) == 4) {
                        float p2min = this.is.readFloat();
                        float p2max = this.is.readFloat();
                    }
                    if ((availableChannels & 8) == 8) {
                        float t1min = this.is.readFloat();
                        float t1max = this.is.readFloat();
                    }
                    if ((availableChannels & 16) == 16) {
                        float tob1min = this.is.readFloat();
                        float tob1max = this.is.readFloat();
                    }
                    if ((availableChannels & 32) == 32) {
                        float tob2min = this.is.readFloat();
                        float tob2max = this.is.readFloat();
                    }
                    break;

                case DF_ID_CONFIG:

                    // Record configuration
                    int startDate = this.is.readInt();
                    int stopDate = this.is.readInt();

                    lw = this.is.readInt();

                    int recordedChannels = lw / 65536;
                    int recordModus = lw % 65536;

                    float trigger1 = this.is.readFloat();
                    float trigger2 = this.is.readFloat();

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

                    short sw = this.is.readShort();

                    int tmp = sw / 256;
                    short recModChannel = (short) tmp;
                    tmp = sw % 256;
                    short recSaveCounter = (short) tmp;

                    short recFastModCounter = this.is.readShort();
                    boolean recEndless = this.is.readBoolean();
                    break;

                case DF_ID_WL_CONVERTED:

                    // Waterlevel converted
                    boolean convertedIntoWaterlevel = is.readBoolean();
                    break;

                case DF_ID_AIR_COMPENSATED:

                    // Airpressure compensation
                    boolean airCompensated = is.readBoolean();
                    break;

                case DF_ID_INFO:

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

    }


    /**
     * 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;
        log.debug("Block          : " + Short.toString(block));
        log.debug("Buffer lengte  : " + Integer.toString(n));

        return block;
    }

    /**
     * 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;
    }
}
  • No labels