/*
* Copyright 2011-16 Fraunhofer ISE
*
* This file is part of OpenMUC.
* For more information visit http://www.openmuc.org
*
* OpenMUC is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenMUC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenMUC. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openmuc.framework.datalogger.ascii;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import org.openmuc.framework.data.ValueType;
import org.openmuc.framework.datalogger.ascii.utils.Const;
import org.openmuc.framework.datalogger.spi.LogChannel;
import org.openmuc.framework.datalogger.spi.LogRecordContainer;
public class LogFileHeader {
private LogFileHeader() {
}
/**
* Generate the standard IES Data Format Header.
*
* @param group
* a group of the LogIntervallContainer
* @param filename
* the name of the file to add the header
* @param loggingInterval
* logging interval in ms
* @param logChannelList
* a list of all channels for this file
* @return the header as a string
*/
public static String getIESDataFormatHeaderString(LogIntervalContainerGroup group, String filename,
int loggingInterval, HashMap<String, LogChannel> logChannelList) {
StringBuilder sb = new StringBuilder();
setHeaderTop(sb, loggingInterval, filename);
// write channel specific header informations
int colNumber = 4;
for (LogRecordContainer container : group.getList()) {
LogChannel logChannel = logChannelList.get(container.getChannelId());
appendChannelSpecificComment(sb, logChannel, colNumber);
++colNumber;
}
List<LogRecordContainer> containers = group.getList();
appendColumnHeaderTimestamp(sb);
Iterator<LogRecordContainer> iterator = containers.iterator();
while (iterator.hasNext()) {
sb.append(iterator.next().getChannelId());
if (iterator.hasNext()) {
sb.append(Const.SEPARATOR);
}
}
sb.append(Const.LINESEPARATOR);
return sb.toString();
}
/**
* Generate the standard IES Data Format Header
*
* @param filename
* the name of the file to add the header
* @param logChannelList
* a list of all channels for this file
* @return the header as a string
*/
public static String getIESDataFormatHeaderString(String filename, List<LogChannel> logChannelList) {
StringBuilder sb0 = new StringBuilder();
StringBuilder sb1 = new StringBuilder();
setHeaderTop(sb0, logChannelList.get(0).getLoggingInterval(), filename);
// write channel specific header informations
int colNumber = 4;
Iterator<LogChannel> iterator = logChannelList.listIterator();
while (iterator.hasNext()) {
LogChannel logChannel = iterator.next();
appendChannelSpecificComment(sb0, logChannel, colNumber);
sb1.append(logChannel.getId());
if (iterator.hasNext()) {
sb1.append(Const.SEPARATOR);
}
++colNumber;
}
appendColumnHeaderTimestamp(sb0);
sb0.append(sb1);
sb0.append(Const.LINESEPARATOR);
return sb0.toString();
}
/**
* Appends channel specific comments to a StringBuilder
*
* @param sb
* @param logChannel
* @param colNumber
*/
private static void appendChannelSpecificComment(StringBuilder sb, LogChannel logChannel, int colNumber) {
String unit = logChannel.getUnit();
if (unit.equals("")) {
unit = "0";
}
ValueType vType = logChannel.getValueType();
String valueType = vType.toString();
int valueTypeLength = 0;
if (vType.equals(ValueType.BYTE_ARRAY) || vType.equals(ValueType.STRING)) {
valueTypeLength = logChannel.getValueTypeLength();
}
String description = logChannel.getDescription();
if (description.equals("")) {
description = "-";
}
createRow(sb, String.format("%03d", colNumber), logChannel.getId(), "FALSE", "TRUE", unit, "other", valueType,
valueTypeLength, description);
}
/**
* Append column headers, the timestamps, in a StringBuilder
*
* @param sb
* @param group
*/
private static void appendColumnHeaderTimestamp(StringBuilder sb) {
// write column headers
sb.append("YYYYMMDD");
sb.append(Const.SEPARATOR);
sb.append("hhmmss");
sb.append(Const.SEPARATOR);
sb.append("unixtimestamp");
sb.append(Const.SEPARATOR);
}
/**
* Sets the top of the header.
*
* @param sb
* @param loggingInterval
* @param filename
*/
private static void setHeaderTop(StringBuilder sb, int loggingInterval, String filename) {
String timestep_sec = String.valueOf(loggingInterval / (double) 1000);
String seperator = Const.SEPARATOR;
// write general header informations
appendStrings(sb, "#ies_format_version: ", String.valueOf(Const.ISEFORMATVERSION), Const.LINESEPARATOR_STRING);
appendStrings(sb, "#file: ", filename, Const.LINESEPARATOR_STRING);
appendStrings(sb, "#file_info: ", Const.FILEINFO, Const.LINESEPARATOR_STRING);
appendStrings(sb, "#timezone: ", getDiffLocalUTC(), Const.LINESEPARATOR_STRING);
appendStrings(sb, "#timestep_sec: ", timestep_sec, Const.LINESEPARATOR_STRING);
appendStrings(sb, "#", "col_no", seperator, "col_name", seperator, "confidential", seperator, "measured",
seperator, "unit", seperator, "category", seperator, Const.COMMENT_NAME, Const.LINESEPARATOR_STRING);
createRow(sb, "001", "YYYYMMDD", "FALSE", "FALSE", "0", "time", "INTEGER", 8, "Date [human readable]");
createRow(sb, "002", "hhmmss", "FALSE", "FALSE", "0", "time", "SHORT", 6, "Time [human readable]");
createRow(sb, "003", "unixtimestamp", "FALSE", "FALSE", "s", "time", "DOUBLE", 14,
"lapsed seconds from 01-01-1970");
}
/**
* Construct a header row with predefined separators and comment signs.
*
* @param col_no
* column number example: #001
* @param col_name
* column name example: YYYYMMDD
* @param confidential
* false or true
* @param measured
* false or true
* @param unit
* example: kWh
* @param category
* example: time
* @param valueType
* example: DOUBLE
* @param valueTypeLength
* example: 8
* @param comment
* a comment
*/
private static void createRow(StringBuilder sb, String col_no, String col_name, String confidential,
String measured, String unit, String category, String valueType, int valueTypeLength, String comment) {
String seperator = Const.SEPARATOR;
String com_sign = Const.COMMENT_SIGN;
String vtEndSign = Const.VALUETYPE_ENDSIGN;
String vtSizeSep = Const.VALUETYPE_SIZE_SEPARATOR;
String valueTypeLengthString = "";
if (valueTypeLength != 0) {
valueTypeLengthString += valueTypeLength;
}
appendStrings(sb, com_sign, col_no, seperator, col_name, seperator, confidential, seperator, measured,
seperator, unit, seperator, category, seperator, valueType, vtSizeSep, valueTypeLengthString, vtEndSign,
comment, Const.LINESEPARATOR_STRING);
}
/**
* appendStrings appends a any String to a StringBuilder
*
* @param sb
* StringBuilder to append a String
* @param s
* the String to append
*/
private static void appendStrings(StringBuilder sb, String... s) {
for (String element : s) {
sb.append(element);
}
}
/**
* Calculates the difference between the configured local time and the Coordinated Universal Time (UTC) without
* daylight saving time and returns it as a string.
*
* @return the difference between local time and UTC as string.
*/
private static String getDiffLocalUTC() {
String ret;
long time = 0;
Calendar calendar = new GregorianCalendar(Locale.getDefault());
time = calendar.getTimeZone().getRawOffset();
time /= 1000 * 60 * 60;
if (time >= 0) {
ret = ("+ " + time);
}
else {
ret = ("- " + time);
}
return ret;
}
}